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.
To use softGlue, you must have the following hardware and software:
Most of softGlue could be used with other IP_EP200 series modules, but the FPGA content and databases supplied in this version are compatible only with the IP_EP201.
To use an earlier version, see "Building softGlue" below.
Any version that agrees with your version of EPICS base should work, though releases earlier than 2.6.5 may require extra effort because they don't automatically adapt to absence of the sscan module.
This module is not required for any essential feature of softGlue, but it provides a nice way for softGlue to signal the completion of an EPICS database operation. Any version that agrees with your version of EPICS base should work; version 1.3 is nice only because it contains an MEDM display for the busy record. If you don't have a copy of this module, don't load softGlue_convenience.db, and don't include softGlue_convenience_settings.req in your autosave request file.
You do not need to be able to program the IP-EP201 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.
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.
Here are a few examples of the sorts of things that can be accomplished with softGlue:
softGlue uses AND/NAND gates (etc.) as opposed to separate AND and NAND gates because we guess that this choice will make more efficient use of FPGA resources, for the sorts of circuits we imagine people building. (But make no mistake: softGlue is, nevertheless, an extremely inefficient application of FPGA resources -- roughly on par with, say, using a personal computer to read documentation.)
Unlike most other synApps modules, however, softGlue publishes the text files needed to boot an IOC in itsdb
directory (as an EPICS module really should, I suppose -- most synApps modules are nonstandard in this respect), rather than in thesoftGlueApp/Db
directory.
svn export https://subversion.xor.aps.anl.gov/synApps/softGlue/tags/R1-1 softGlue-1-1
softGlue/configure/RELEASE
, to specify the paths to EPICS_BASE, ASYN, and
IPAC.
softGlueApp/src/drvIP_EP201.c
to change the definition of the macro,
DO_IPMODULE_CHECK
, like so: #define DO_IPMODULE_CHECK 0
make
in the top-level directory, using the same make
executable used to build EPICS base.
The build will issue a warning that it can't expand all macros in substitution files. This is not an error; unexpanded macros are intended to be defined at boot time.
configure/RELEASE
RELEASE
file to define the following names:
SOFTGLUE=<path to the softGlue module>
ASYN=<path to the asyn module>
IPAC=<path to the ipac module>
CALC=<path to the calc module>
BUSY=<path to the busy module>
BUSY
is an optional add-on for you to use with softGlue. If the busy module is available, you can arrange for EPICS database processing to wait for a signal from softGlue hardware before declaring itself to be finished. ThesoftGlue_convenience.db
database loads busy records for this purpose, and thesoftGlueConvenience.adl
display file contains menu items to display the records. Nothing else in softGlue depends on the busy module.
xxxApp/src
Makefile
or a *Include.dbd
file so that the file
softGlueSupport.dbd
is included in the .dbd
file the
IOC loads at boot time. You'll also need files from asyn, ipac, calc, and busy,
if you're not already including them.For a Makefile:
iocxxx_DBD_vxWorks += softGlueSupport.dbd drvIpac.dbd asyn.dbd calcSupport.dbd busySupport.dbdFor the .dbd file that will be loaded into a vxWorks IOC:
include "softGlueSupport.dbd"
include "drvIpac.dbd"
include "asyn.dbd"
include "calcSupport.dbd"
include "busySupport.dbd"
Makefile
so that the IOC executable is linked with the
softGlue
library. You'll also need libraries from the asyn, ipac, calc,
and busy modules. The order in which libraries are named is sometimes
important.
Example:
xxx_LIBS_vxWorks += calc asyn Ipac softGlue busy
iocBoot/iocxxx
softGlue/iocBoot/iocSoftGlue/softGlue.cmd
to your IOC directory,
which I'll call iocBoot/iocxxx
, and edit the
dbLoadRecords()
commands in your copy of softGlue.cmd
to
define the macro P
, so that it's unique to your IOC.
If you'll have more than one IP_EP201 module in an IOC, you'll also need to maintain separate definitions for the macro,H
, and for asyn port names and addresses associated with the modules. Port names are the first arguments to the functionsinitIP_EP201(), initIP_EP201SingleRegisterPort()
, and the values of the macrosPORT
,IPORT
, andOPORT
, supplied indbLoadRecords()
commands. Addresses are the sixth argument supplied toinitIP_EP201()
, and the values of macrosIADDR
andOADDR
.
st.cmd
, before the call to
iocInit()
.
< softGlue.cmd
save_restore.cmd
:
set_requestfile_path(softglue, "softGlueApp/Db")
Careful! the firstsoftglue
must be all lowercase, because this is how the path variable is defined incdCommands
.
auto_settings.req
(or whatever you've
named the file used to save/restore PV's of arbitrary type):
file softGlue_settings.req P=$(P) H=softGlue:
where the macros P
, and H
agree with those in
softGlue.cmd
.
xxxApp/op/adl
softGlueMenu.adl
display with the macros P
, and
H
, as defined in iocBoot/iocxxx/softGlue.cmd
.
The file softGlueApp/op/adl/softGlueTop.adl
contains an example button.
If you figure out how to use softGlue with some other display manager, please tell us about it, so we can include your work in the next version of softGlue. The MEDM-display files included in softGlue make heavy use of MEDM'scomposite file
, and I don't know the extent to which a comparable feature exists in other display managers. softGlue's use ofcomposite file
is purely a display-development convenience.
setenv EPICS_DISPLAY_PATH $EPICS_DISPLAY_PATH':'$SOFTGLUE/softGlueApp/op/adl
cd <applicationTop>
make rebuild
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/NAND" 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.
User Menu
softGlueMenu.adl
is the top softGlue display, which serves mostly to call up other
displays. The menu labelled CONNECTED
specifies the period at which the values of connected
signals are sampled for display to the user. The menu labelled UNCONNECTED
specifies
the period at which the values of unconnected signals are sampled for display to the user.
Most softGlue displays are not interrupt driven. (That would be a disaster, because inevitably some signals will change state at high frequency.) So, the states of inputs and outputs must be sampled periodically, for display to the user. It seems wasteful to poll signals that aren't being used, but we don't have very good information about which signals those are. A signal that has been connected to some other signal is certainly being used, so it makes sense to discriminate on that basis.We've found that it's confusing for users if either of these poll periods are greater than around 1 second. We've also found that polling everything at .1 second uses only a few percent of an MVME2700 CPU.
AND/NAND
On the left of the AND gate are the inputs, each comprised of a blue "= button", a yellow text-entry field, a number, and what's intended to look like a red LED. On the right are essentially the same things in reverse order, but an output's text-entry field is a different color. The text-entry fields are used to connect signals together, and the color difference is intended to remind you of the only rule governing signal connections: if you connect two or more outputs together, those outputs won't work.
softGlue outputs are engineered to ensure that you can't break anything by connecting outputs together, but the circuit won't be useful until you fix the error, because the states of outputs connected together are undefined. Currently, softGlue doesn't signal this error by putting offenders into an alarm state.
The yellow text-entry box controls an input. You have five options:
This directly writes a logic value (optionally, a pulse) to the input.
softGlue will parse everything that looks numberish, and convert to a floating point value. This sets the input to a logic value: 0 if the nearest integer to the converted value is zero, 1 if it's not.
Allowing floats, and extra characters after the number makes it easier to drive softGlue inputs with calc records, replies from serial devices, etc.
The strings "0!" and "1!" (possibly followed by other ignored characters) direct softGlue to
write a pair of logic values: "0!" writes "0" followed immediately by "1"; "1!" writes "1" followed
immediately by "0". The time interval between writes is system dependent, and not at all
guaranteed, but it should be much smaller than the interval you could achieve from separate writes.
On an MVME2700, I measure around 6 μs.
This names the signal, and connects it to all other signals with the same name (or with the
same name followed by '*
', as described below). Case is significant in comparing
signal names.
Note that you can't connect signals implemented in different IP-EP201 modules using their text-entry boxes. To accomplish this, you must connect the signals to field I/O and make a physical connection.
*
' to an input-signal name.
Now that we have this capability, we probably no longer need circuit elements to provide complementary outputs.
Whatever option you choose, you can define at most fifteen different signal names. When you try
to define the 16th name, softGlue will erase whatever you wrote, and put the record into the
"INVALID" alarm state. (But note, for example, that reset
and reset*
are
not different signal names, because the trailing '*
' is not regarded as part of the
name; it merely describes how the signal should be used.)
Text-entry boxes for output signals won't accept names beginning with a number, or ending with
'*
'. (softGlue will simply strip the offending characters, and leave the rest.)
Signal names beginning with a number cannot be connected to inputs, because the leading number would be misinterpreted by input-signal-name parsing as a direct-write command. Output-signal names ending with '*
' are logically sensible, but are not permitted to simplify the implementation of '*
' appended to input-signal names.
A signal's blue "= button" is used to find all other signals to which the signal is connected. While a signal's "= button" is pressed, input signals connected to it flash green boxes, and output signals connected to it flash orange boxes. If you ever see two or more orange boxes flashing at the same time, you have outputs connected together, and your circuit won't work.
The little red and black filled circles (LED's), and the numbers next to them, display the states
of their signals. These display elements are updated at the period specified in the
softGlueMenu.adl
display. If you want the EPICS PV name corresponding to a signal's
logic value, this is the PV name to use.
The open circle ("bubble") in the top output's signal path indicates that the output is inverted. You'll also see this bubble in some input signal paths. Any signal going through a bubble is inverted.
For completeness, here's the truth table for an AND gate:
input1 | input2 | output | |
---|---|---|---|
0 | x | 0 | |
x | 0 | 0 | |
1 | 1 | 1 |
'x' means "either 0 or 1".
OR/NOR
input1 | input2 | output | |
---|---|---|---|
0 | 0 | 0 | |
1 | x | 1 | |
x | 1 | 1 |
XOR/XNOR
input1 | input2 | output | |
---|---|---|---|
0 | 0 | 0 | |
0 | 1 | 1 | |
1 | 0 | 1 | |
1 | 1 | 0 |
D FlipFlop
The input signal labelled ">" is the "clock" input. Unlike other signals, clock inputs are edge sensitive. All clock inputs in softGlue act on the rising edge of the input signal.
SET | CLEAR | D | > (clock) | Q | |
---|---|---|---|---|---|
0 | 0 | x | x | undefined | |
0 | 1 | x | x | 1 | |
1 | 0 | x | x | 0 | |
1 | 1 | any | rising edge | DBEFORE (value D had immediately before the rising edge of the clock signal) |
2-Input Multiplexer
When SEL==0
, OUT=IN0
. When SEL==1
, OUT=IN1
.
2-Output Demultiplexer
When SEL==0
, OUT0=IN
, and OUT1
is undefined (currently
0). When SEL==1
, OUT1=IN
, and OUT0
is undefined (currently
0).
Up Counter (32-bit Counter)
EN==1
enables the clock (">") input, whose rising edge increments the counter value.
Down Counter (16-bit Preset Counter)
EN==1
enables the clock (">") input, whose rising edge decrements
the counter value. When LOAD==1
the counter is loaded with the value applied to the
PRESET
input. (Currently, this is a 16-bit value, but the plan is to increase it to 32
bits.) While LOAD==1
, the counter does not count down. While LOAD==0
and
EN==1
, a rising edge at the clock input decrements the counter. When the counter value
reaches 0
, the output Q
goes to 1
; the next rising edge of
the clock returns Q
to 0
(regardless of the states of EN
and
LOAD
).
Divide By N
EN==1
enables the clock (">") input. Every N
'th rising
edge of the clock drives Q
to 1
. The next rising edge returns
Q
to 0
. In softGlue version 1.1, the RESET
signal doesn't do
anything.
8 MHz internal clock
An 8 MHz clock derived from the IndustryPack clock is available to softGlue circuitry as a free standing output.
Field I/O
This display allows you to connect field I/O signals to each other and to softGlue circuits. Note that a "Field Input Bit" looks like and behaves as a softGlue output, because what you're actually controlling is the output of a buffer driven by the field-input signal. Similarly, a "Field Output Bit" looks like and behaves as a softGlue input, because you're actually controlling the input of a buffer that drives the field-output signal.
The signals in this display are the field inputs (pins 1-16 on the IP-EP201's ribbon connector) and field outputs (pins 17-32 on the ribbon connector). These I/O pin choices are hard-wired in the FPGA content.
Although you can't change the field-wiring I/O assignments, you can easily change the "CONNECTOR #" numbers in this display -- for example, to support a custom signal-breakout module. The numbers are defined insoftGlueApp/Db/softGlue_FPGAContent.substitutions
, as the macroIOPIN
supplied tosoftGlue_FieldOutput.db
andsoftGlue_FieldInput.db
.
Field I/O Interrupt support
The 16 input lines supported by softGlue can generate interrupts on rising edges, falling edges, both, or neither. You control this by setting the "INTERRUPT ENABLE" menu to "Rising", "Falling", "Both", or "None", respectively. Field output lines can, in principle, also generate interrupts, but this hasn't been implemented yet, so the output interrupt support doesn't function.
Interrupts are throttled by softGlue's interrupt handler. If more than four interrupts have occurred and not been handled, softGlue will disable interrupts from the offending bit, by setting the bit's "INTERRUPT ENABLE" menu to "None", and it will direct your attention to the change by drawing a red box around the menu control. The box will be erased the next time the menu is written to.
The number of unhandled interrupts that triggers throttling is adjustable by modifying drvIP_EP201.c. You must change the definition ofMAX_IRQ
, and you must also ensure that the asyn ring buffers for interrupt driven PV's is larger thanMAX_IRQ
. (The default ring buffer size is 10. Asyn documentation describes how to change it.)
When an interrupt occurs, you can have the signal value written to an EPICS PV, by writing an EPICS link description into the purple box labelled "ON INTERRUPT, WRITE SIGNAL VALUE TO THIS PV", as shown for input 16 in the above screen shot.
In softGlue displays (and in most other synApps displays), standard EPICS links are displayed as purple text-entry boxes, in which you describe the link you want to make. For purposes here, an EPICS link description is the name of an EPICS PV, followed by one of the following link attributes:
NPP | (default) write value, but do not cause processing. |
PP | write value and cause processing (if the record containing the PV is "Process
Passive", which means that it's SCAN field has the value "Passive"). You should use this attribute unless you have some reason not to use it. |
CA | write value and let the record containing the PV decide whether or not to process. |
EPICS will tack on the string " NMS". This alarm-propagation attribute is not something end users need to worry about.
For example, to cause a link to write effectively to the top input of the first AND/NAND gate
(whose PV name is xxx:softGlue:AND-1_IN1_Signal
, you would write the following
into a purple box:
xxx:softGlue:AND-1_IN1_Signal PPIf you only write the PV name, EPICS will supply the link attribute
NPP
, and your link
will write a value, but the value won't have any effect until the next time the record processes.
(For most PV's in softGlue, the value written by an NPP link won't even be displayed until the
record processes.)
Everything on one display
This display shows everything in softGlue except interrupt support.
Convenience
This display controls two pulse generators implemented in EPICS, with links allowing them to write to a softGlue input (that is, to a yellow box), and, similarly, two clock generators implemented in EPICS. The display also has MEDM related-display callups for two busy records,
The use of EPICS links (the purple boxes in the above display) is described above in the section "About EPICS links", in the documentation of "Field I/O Interrupt support".
BusyRecord
This display controls the value, output link, and forward link of a busy record. In the anticipated use with softGlue, one would have some EPICS record outside of softGlue set the busy record to "Busy" (using a PP link), and arrange for a softGlue interrupt bit (see "Field I/O Interrupt support", above) to use its EPICS-output link to clear the busy record to "Done" (using a CA link).
The use of EPICS links (the purple boxes in the above display) is described above in the section "About EPICS links", in the documentation of "Field I/O Interrupt support".
It's important to set a busy record to "Busy" using a PP link, because the purpose of a busy record is to represent some external processing as EPICS processing. This allows EPICS' execution tracing to signal the completion of the processing. EPICS only traces processing started or propagated with a PP link.It's important to clear a busy record to "Done" with a CA link, because an EPICS PP link will decline to process any record that is already processing. The busy record is written so that a CA put will succeed in clearing it and causing its processing to appear done to EPICS.
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
No doubt your PREFIX will be different from mine, but it should be$(P)$(H)
from your copy ofsoftGlue.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 command restores the circuit:
burtwb -f myCircuit.snap
Negative going signals 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.
Na
, can be calculated with the following
formula:
Na = ((VBAS+VELO)/2)*ACCL/MRES
where, VBAS
, VELO
, ACCL
, and MRES
are
motorRecord fields.
The number of constant-speed steps, Nc
, is then
Nc = ((VALend - VALstart)/MRES) -
2*Na
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 16, gates out
the first 11 (the value of DnCntr-1_PRESET
), and from then on sends motor
pulses to output pin 2 until a total of 51 (the value of DnCntr-2_PRESET
) have
been sent. The circuit is reset by setting OR-1_IN1
(that is, writing "1" to
it), and enabled for another motor move by clearing OR-1_IN1
.
The circuit includes some diagnostics, and a mechanism for testing:
UpCntr-1
counts all motor pulses; UpCntr-2
counts gated
motor pulses. Both counters are reset by the same signal that resets the gate circuit.
OR-1_IN1
.
(OR-1_IN2
remains always at 0.)
Down counter DnCntr-1
, and flipflop DFF-1
, together produce a gate
signal that is 0 after a reset, and that goes to 1 after DnCntr-1_PRESET
motor
pulses. Down counter DnCntr-2
, and flipflop DFF-2
, together produce a
gate signal that is 1 after a reset, and that goes to 0 after DnCntr-2_PRESET
motor
pulses. We load the number of acceleration steps into DnCntr-1_PRESET
, and the
number of acceleration steps plus constant-speed steps into DnCntr-2_PRESET
.
AND-1
combines the gate signals produced above into a signal that is 1 while
the motor is moving at constant speed.
AND-2
gates the negative going motor pulses, using what was described
earlier as a positive-going-pulse gate, by inverting the "motor" signal before applying it
to the gate.
Note that the down counters are clocked by (rising edges of) "motor", to produce the signal used to gate "motor*". This choice avoids a race condition between simultaneous rising edges of "gateOut" and "motor". (This circuit gates negative going motor pulses, so another way to make the point is to say that the trailing edge of a motor pulse is used to produce a gate that will be ready in plenty of time for the leading edge of the next motor pulse.)
Calculations for the circuit are shown in the following screen capture of a transform record.
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 the file EP200_FPGA.hex.
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.
These field I/O registers are implemented separately from softGlue, and provide provide more flexibility than softGlue is able to take advantage of. For example, the user can choose which I/O bits are inputs and which are outputs, but softGlue is compatible with only one of the possible choices.
msi
to produce partially
resolved databases loaded by dbLoadRecords().
softGlue's driver implements three asyn ports to connect EPICS records with registers implemented in the IP-EP201 module's FPGA. Two 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 third 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 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.
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 inputs and outputs are supported by two independent sets of binary input and output records:
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 CONNECTED
or
UNCONNECTED
menus on the softGlueMenu.adl
display.
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 entries on the
softGlueFieldIO_Int.adl
display. The polling periods for inputs
and outputs are specified separately.
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: | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
function: | N | R | U | A3 | A2 | A1 | A0 |
where
N | invert-signal bit |
R | read bit |
U | user-write bit |
An | bus-line address bit |
bit: | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
function: | R | A3 | A2 | A1 | A0 |
where R and An are as defined above for the input register.
Address Offset | Function | Description | Read/Write |
---|---|---|---|
0 | Control/Status | Field-I/O direction, IRQ status | Read/Write |
1 | Field I/O Write Data | Write Field I/O ONLY when dir = 1 | Read/Write |
2 | Field I/O Read Data | Read Field I/O ONLY when dir = 0 | Read |
3 | Rising IRQ Status Bits | Which Bits are causing interrupt from field I/O on transition to 1 | Read/Write* |
4 | Rising IRQ Interrupt Enable Bits | Which Rising edge bits have IRQ Enabled | Read/Write |
5 | Falling IRQ Status Bits | Which bits are causing interrupt from field I/O on transition to 0 | Read/Write* |
6 | Falling IRQ Interrupt enable bits | Which bits have falling IRQ enabled | Read/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. |
Bit | Function | Value | Description |
---|---|---|---|
0 | Field I/O Direction Lower 8-Bits | 0=Input, 1=Output | Sets I/O direction for the lower 8 field-I/O bits |
1 |   | 0 |   |
2 |   | 0 |   |
3 |   | 0 |   |
4 |   | 0 |   |
5 | Falling Edge IRQ Present | 1=Present | Falling Edge interrupt from bits 0-7 sets bit to 1 |
6 | Rising Edge IRQ Present | 1=Present | Rising Edge interrupt from bits 0-7 sets bit to 1 |
7 | Lower 8-bits IRQ Present | 1=Present | Interrupt from bits 0-7 sets bit to 1 |
8 | Field I/O Direction Upper 8-Bits | 0=Input, 1=Output | Sets I/O direction for the upper 8 field-I/O bits |
9 |   | 0 |   |
10 |   | 0 |   |
11 |   | 0 |   |
12 |   | 0 |   |
13 | Falling Edge IRQ Present Upper 8-Bits | 1=Present | Falling Edge interrupt from bits 8-15 sets bit to 1 |
14 | Rising Edge IRQ Present Upper 8-Bits | 1=Present | Rising Edge interrupt from bits 8-15 sets bit to 1 |
15 | Upper 8-bits IRQ Present | 1=Present | Interrupt from bits 8-15 sets bit to 1 |
------------------------------------------------------------------------------ Deployment considerations We need to ensure that the software agrees with the FPGA programming. Software dependence on FPGA content is of two 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 1.1 implementation of softGlue has several AND/NAND gates, several OR/NOR 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 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/NAND gate #1 is associated by address with a 'single 16-bit register' component. 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 take responsibility themselves for agreement between software and firmware. ------------------------------------------------------------------------------ Programming the FPGA via the IP bus. The IP-EP201 board has to be prepared for this by moving the DIP jumper to "IP BUS". 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