LWDAQ Function Generator (A3050)

© 2024 Nathan Sayer, Open Source Instruments Inc.
© 2024 Kevan Hashemi, Open Source Instruments Inc.


TCL Interface
TCP/IP Interface
Hardware Description
Data Interface


In an attempt to automate part of the QC2 procedure for SCTs, we begin the design of a function generator that can be controlled through an RJ-45 socket with LWDAQ. We begin by looking at the design done by Michael Bradshaw (A3031). With our new design, we plan to use a similar method to change frequency output but allow the device to be controllable over a socket without a LWDAQ driver involved. This instrument will allow us to perform a frequency sweep on our circuits and measure the response in a LWDAQ instrument. We begin with the same RCM6700 module and logic as the ALT baseboards. This will provide communication over the socket. The logic will then transmit a signal through two identical channels, starting with an 8-bit DAC. This will output a rough sinusoid that can then be smoothed out with an RC circuit. We switch to different RC circuits depending on the update rate of the signal using DG411Y chips. We include power LEDs and indicator lights to make testing the board easier.

Figure 1: A3050B LWDAQ Function Generator in its enclosure.


[13-JUN-24] The following versions of the Function Generator (A3050) exist.

Version Features Comment
A3050A Two-channel, no attenuators. Prototype, discontinued.
A3050B Two-channel, with attenuators. First production version.
Table 1: Versions of the Function Generator (A3050).


S3050A: Schematic for A3050A.
S3050D: Schematic for A3050B.
A305001A: KiCAD project for PCB.
A305001B: KiCAD project for PCB.
A305001C: KiCAD project for PCB used in A3050A.
A305001D: KiCAD project for PCB used in A3050B
S3050DCA: Schematic for prototype isolated DC-DC converter.
S3050DCB: Schematic for production isolated DC-DC converter.
A305002A: KiCAD project for PCB used in A3050DCA.
A305002B: KiCAD project for PCB used in A3050DCB.
Firmware Repository: Firmware Repository

The first version of the PCB, the A305001A, did not route the feedback of the op-amps correctly, and as a result the op-amps consumed too much current. We also forgot to include a programming extension for the logic chip and as a result we had to solder some wires to individual pins. We also plan to replace the 80-MHz clock currently on the board with one that has a bigger footprint. The board has plenty of space and it will be easier to solder and test.

Tcl Interface

[13-JUN-24] The Tcl interface for the Function Generator (A3050) is provided by the LWFG (Long-Wire Function Generator) package, which you will find in the LWDAQ package directory. Load the LWFG package into your LWDAQ process with "package require LWFG". The LWFG package provides routines to configure your function generator to produce sine, square, and triangle waves. The LWDAQ_configure routine takes six parameters.

LWFG_configure ip ch_num waveform frequency v_lo v_hi

Here, ip is the IP address of the function generator's TCPIP server. Use the Configurator Tool to set up the function generator's TCPIP interface. This function generator can be controlled entirely through the Function Generator tool in LWDAQ which can be found in the Tools-> More dropdown menu. The ch_num is either 1 or 2 for the A3050B. The waveform is either "sine", "square", or "triangle". The frequency is in Hertz. The two voltages v_lo and v_hi are the voltages of the minimumm and maximum points in the waveform respectively.

TCP/IP Interface

[13-JUN-24] The A3050 is a TCPIP server that obtains both power and performs communication over a single RJ-45 socket. We plug the A3050 into a Power over Ethernet (PoE) switch. We use the Configurator Tool to set up the function generator's TCPIP interface. We can resest the A3050's IP address to by pressing the red reset button and the brown configure button at the same time, release the reset button and keep pressing the configure button for a few seconds.

Control Space Address (Hex)Contents
00Hardware identifier
12Hardware version
13Software version
18Data address 1
19Data address 2
1AData address 3
1BData address 4
3FData portal
Table 2: Function Generator Controller Space Adress Map.

We communicate with the A3050 over TCPIP using the LWDAQ Messaging Protocol. These messages allow us to read and write from individual byte locations in control space, and to write blocks of data to locations in date space. The LWDAQ routines that provide LWDAQ messaging are contained in Driver.tcl. All LWDAQ commands are listed and described in the LWDAQ Command Reference. We write to a byte in control space with LWDAQ_byte_write. We read with LWDAQ_byte_read.

Writing to the data space is a two-step process. We first use LWDAQ_set_data_addr to write four bytes to the data address, which resides in the control space. We then use LWDAQ_stream_write to write a block of data to the data portal, which is a single byte in control space. The LWFG package does not use any byte read or write routines, but instead relies upon higher-level routines defined in Driver.tcl that make it easy for us to work in the A3050's data space. The code below, taken from package LWFG V1.4, demonstrates the use of these routines with the A3050.

# Open a socket to the function generator.
set sock [LWDAQ_socket_open $ip]

# Write the waveform values to the waveform memory.
LWDAQ_set_data_addr $sock $LWFG(ch$ch_num\_ram)
LWDAQ_stream_write $sock $LWFG(data_portal) [binary format c* $values]

# Set the filter configuration register.
LWDAQ_set_data_addr $sock $LWFG(ch$ch_num\_rc)
LWDAQ_stream_write $sock $LWFG(data_portal) [binary format c [expr $filter]]

# Set the clock divisor.
LWDAQ_set_data_addr $sock $LWFG(ch$ch_num\_div)
LWDAQ_stream_write $sock $LWFG(data_portal) [binary format I [expr $divisor - 1]]

# Set the waveform length.
LWDAQ_set_data_addr $sock $LWFG(ch$ch_num\_len)
LWDAQ_stream_write $sock $LWFG(data_portal) [binary format S [expr $num_pts - 1]]

# Wait for the controller to be done with configuration.
set id [LWDAQ_hardware_id $sock]

# Close the socket.
LWDAQ_socket_close $sock

The final call to LWDAQ_hardware_id is a way to wait for the A3050 to finish all the writes to the data space before we close the socket. If we close the socket too soon, the A3050 will abandon its work.

Data Interface

All of the registers necessary for controlling the function generator are located in the data space.

Data Address (Hex)Contents
0000...1FFFSample values, Channel 1
4000...5FFFSample values, Channel 2
8000RC filter switch controller, Channel 1
8001RC filter switch controller, Channel 2
8002Divisor, Channel 1, Byte 3
8003Divisor, Channel 1, Byte 2
8004Divisor, Channel 1, Byte 1
8005Divisor, Channel 1, Byte 0
8006Divisor, Channel 2, Byte 3
8007Divisor, Channel 2, Byte 2
8008Divisor, Channel 2, Byte 1
8009Divisor, Channel 2, Byte 0
800AWaveform length, Channel 1, Byte 1
800BWaveform length, Channel 1, Byte 0
800CWaveform length, Channel 2 Byte 1
800DWaveform length, Channel 2 Byte 0
800EAttenuation for both channels
Table 3: Function Generator Data Adress Space Map.

As an example, we will generate a 5V 100kHz square wave with an offset. We begin by writing [128, 255 (dec)] to the first two locations in the data space. The full range of DAC values is 0 to 255 (dec) so if we change between 128 and 255 the waveform will be offset by 5V and have a ptp amplitude of 10V. We then set the waveform length to 2 by writing [0, 1 (dec)] to 800A. Lastly, we write [0, 0, 0, 199 (dec)] to location 8002. This determines the divisor for the clock that sets the speed at which the function generator is reading from RAM. Below is an equation for determining the frequency of the output waveform.

Figure 2: Equation for calculating the frequency of the output waveform and its sample frequency using variables set in the data space.

We use some variables to make the equations look neat. We define "waveform frequency" as the frequency of the sine wave, square wave, or arbitrary waveform that is generated on the output of the function generator. We define "sample frequency" as the rate at which the function generator reads from the RAM, moving onto the next sample value. We define "waveform length" as a unitless variable equal to the number of samples required to complete one cycle of the output waveform. Lastly, we define "clock divisor" as the value we provide in order to change the sample rate. We provide a plot of output voltage versus DAC value below such that anyone operating the function generator can generate any voltage within the acceptable range. For this example waveform, we do not need to write to the RC filter registers because the default RC filter is the smallest time constant possible which gives us the sharpest square wave possible. Different possible time constants the function generator can use are in the table below:

BinaryHexDecimalResistanceCapacitanceTime Constant
00000001010151 Ω250 pF (parasitic)12.5 ns
00010001111751 Ω1 nF51 ns
000100101218110 Ω1 nF110 ns
000101001420270 Ω1 nF270 ns
000110001824560 Ω1 nF560 ns
00100001213351 Ω22 nF1.12 μs
001000102234110 Ω22 nF2.42 μs
001001002436270 Ω22 nF5.94 μs
001010002840560 Ω22 nF12.3 μs
01000001416551 Ω500 nF25.5 μs
010000104266110 Ω500 nF55 μs
010001004468270 Ω500 nF135 μs
010010004872560 Ω500 nF280 μs
100000018112951 Ω20 μF1.02 ms
1000001082130110 Ω20 μF2.2 ms
1000010084132270 Ω20 μF5.4 ms
1000100088136560 Ω20 μF11.2 ms
Table 4: RC filter byte values.

The two data address locations that control the RC filters for both channels use 1 byte to control all 8 switches within one channel. The diagram below shows us an example of all the switches being open with the exception of 100 Ω. For more info on how LWDAQ messages are used to communicate with the control space, see LWDAQ Specification. For an example of using control space to create a data space through a data portal, see LWDAQ Driver Manual.

Channel NumberData Address (Hex)Bit of 8-Bit RegisterPassive Component Being Switched
Table 5: RC filter byte values. Writing "1" to a bit causes the passive component to be selected.

Here we use the default 12.5ns time constant which can be set by resetting the function generator or by writing 01 to the location 8000 (Hex) to the data space. We also choose to not attenuate the signal at all so we do not have to write to that register seeing as the default is no attenuation. If we were to attenuate the signal we could use the table below to choose by how much the signal would be attnuated:

Channel NumberData Address (Hex)Bit of 8-Bit RegisterAttenuator Being Selected
Table 6: Attenuator byte values. Writing "1" to a bit causes the attenuator to be selected.

The resulting waveform is below:

Figure 3: Square wave, offset= 5V, waveform length= 2, RC= 1, divisor= 199.

The function generator's registers always reset to the same values, see table below:

ParameterReset Value (Dec)
Sample Values, Channel 1128 (Output = 0V)
Sample Values, Channel 2128 (Output = 0V)
RC filter switch controller, Channel 11
RC filter switch controller, Channel 21
Divisor, Channel 1, Bytes 0-3All 0
Divisor, Channel 2, Bytes 0-3All 0
Waveform Length, Channel 1, Bytes 0-1All 0
Waveform Length, Channel 2, Bytes 0-1All 0
Attenuation switch controller, both channelsAll 0
Table 7: Reset values for programmable parameters.

The waveform generated has a maximum amplitude of +/- 10V but if the channel is terminated with 50 ohms then the maximum amplitude of the waveform becomes +/- 5V. This function generator is designed to provide proper transmission down a 50-ohm coaxial cable terminated with a 50-ohm resistor.

Figure 4: Plot of output voltage vs. DAC values

Next, we will generate a 10V 1.25MHz sine wave. We begin by writing the values [128, 152, 176, 198, 218, 234, 245, 253, 255, 253, 245, 234, 218, 198, 176, 152, 128, 103, 79, 57, 37, 21, 10, 2, 0, 2, 10, 21, 37, 57, 79, 103 (dec)] to the first 32 locations in the data space. Lastly, we write [0, 31 (dec)] to address 800A. This changes the waveform length to allow for the first 32 DAC values to be read out repeatedly. Notice that writing 31 as the waveform length allows for a waveform of 32 samples. The actual waveform length will be one more than the value written to the register. We do not change the divisor because we wish to generate 1.25MHz which is achieved with no divisor and a waveform length of 31. The resulting waveform is below:

Figure 5: Sine wave, waveform length= 32, RC= 1, divisor= 0.

Finally, we will generate a smoothed 10V 10kHz sine wave. The 1.25 MHz sine wave was fast enough that it didn't require a base load capacitor to smooth out. Something slower will have noticeable steps if not smoothed. We begin by writing the same DAC sine wave values as the first waveform [128, 152, 176, 198, 218, 234, 245, 253, 255, 253, 245, 234, 218, 198, 176, 152, 128, 103, 79, 57, 37, 21, 10, 2, 0, 2, 10, 21, 37, 57, 79, 103 (dec)] to the first 32 locations in the data space. We then write [0, 31 (dec)] to address 800A to guarentee the waveform reads all 32 DAC values and only those 32 DAC values. We also write [0, 0, 0, 124 (dec)] to location 8002 in order to change the waveform's frequency by a factor of 125. If we write [1 (dec)] to address 8000 then the output will look something like this:

Figure 6: Sine wave, waveform length= 32, RC= 1, divisor= 124.

Notice how we can see each sample as a step rigidly separated from the others. To avoid this, we can write [34 (dec)] to location 8000 which gives us a 10us RC filter. The resulting waveform has about 13% less amplitude but looks much smoother:

Figure 7: Sine wave, waveform length= 32, RC= 34, divisor= 124.

Hardware Description

We want to design the function generator such that it can output frequencies from a few megahertz to less than one hertz. To accomplish the faster frequencies we load an 80MHz clock onto the board going directly to logic. This clock signal is then divided by an amount determined by a register and then used as the trigger for when to read from RAM. This way we can slow the clock down by dividing its frequency by some integer. The LCMXO2-7000HC then reads the RAM values and writes them to the 8-bit DAC we load on the logic output with 0.1 percent precision resistors which gives us a waveform with steps in it. Each step represents reading a new RAM value. This rigid waveform however does not have an average value of zero volts because the logic outputs a DAC voltage between 0V and 3V3. To set the average value to zero we tie the DAC output to the non-inverting input 3V3 to the inverting output through a 1k resistor. Since the DAC output should be centered around 1V65 we use a feedback resistor of 1k causing the signal on the output to have a gain of 2 and be offset by 1V65. We then run the signal through two analog switches that allow the user to select which RC filter they would like to use to smooth out the jagged waveform. The filtered waveform is then passed through another amplifier with a gain of 3 and no offset. Afterwards the output of this amplifier is connected to a 2k resistor followed by an analog switch which controls which resistors are connecting the signal to ground. Using this method we can attenuate a signal using control lines from our logic chip. Lastly, the signal is put through an amplifier with a gain of 1 that acts as a buffer which can supply the current necessary for the final waveform. This signal is then put through a 50R 3W resistor and goes out to a BNC connector. We repeat this method using different I/O pins on the logic to create a second signal output. Now we can use this function generator to output an arbitrary waveform of any frequency between less than 1 Hz and 5MHz with an amplitude of up to +/- 10V.

Figure 8: A3050B LWDAQ Function Generator inside its enclosure with the lid removed, front view.

Figure 9: A3050B LWDAQ Function Generator inside its enclosure with the lid removed, top view.


[20-OCT-23] Create manual page.

[25-OCT-23] We receive new PCBs (A305001B) and assemble one. We notice that as soon as power is supplied, the +/-12V DC-DC converter begins buzzing. The logic chip can program so we now have a working extension, but we found that we must remove the feedback capacitors (10pf) on each op-amp in order to avoid drawing too much current. After removing these capacitors, we put a 3.3V 32.768kHz signal through both DAC channels and watch it propagate through the amplifiers. Each channel outputs a 10Vptp 32.768kHz signal with a 0V average.

Figure 10: Input (square) and output (shaped) of the A3050A LWDAQ function generator using a 32.678kHz clock signal.

[18-DEC-23] We program the controller (LCMXO2-7000HC) with a relay interface that maps various address spaces to variables needed to output a function. The data portal is located in the highest location in the control space.

[24-JAN-24] To avoid supply shortage issues later on, we develop a DC-DC converter using the LT8306 no-opto isolated flyback converter. Using the LT8306 datasheet, we come to the following design:

Figure 11: Schematic for PoE to 24V DC-DC converter.

Once assembled, we test the converter by slowly ramping up its input voltage with a DC benchtop power supply and measuring its current consumption as well as its output voltage.

Figure 12: Current Consumption and Output Voltage vs. Input Voltage with a 200 Ohm load.

We then use these measured values to calculate the input power and output power. The effieciency measured in the graph below is defined as the output power divided by the input power.

Figure 13: Efficiency vs. Input Voltage with a 200 Ohm load.

[29-JAN-24] We notice that with a 0.01 Ohm sense resistor the output voltage varies greatly based on input voltage. We increase the sense resistor to 0.025 Ohms and notice that the output voltage stabalizes with respect to input voltage.

[07-MAY-24] We change the transformer used and attempt to output different voltages, measuring efficiency while increasing the output power.

Figure 14: Efficiency vs. Output Load for various transformers and output voltages.

[17-APR-24] We get a new PCB for the DC-DC converter, A305002B and test. This new PCB allows us to choose between one output voltage and two differential output voltages by loading 0R resistors on some P0805 footprints. This allows us to use one PCB for different converters, versions below:

VersionR6 ValueR7 ValueR8 ValueOutput Voltage
Table 7: Version table for A3050DC. SC = Short Circuit, OC = Open Circuit.

[17-APR-24] We assemble a converter in the ±12V configuration and plot its output voltage vs its output current for various values of R_sense. Results below:

Figure 15: Output Voltage vs. Output Current for the A3050DC-D12 with various sense resistors.

[18-APR-24] We measure the voltage at the drain of the MOSFET and the output of the transformer using an oscilloscope at various time divisions. Plots below.

Figure 16: Voltage at Q1-D (Channel 1) and D3-A (Channel 2) with 25 μ time divisions.

Figure 17: Voltage at Q1-D (Channel 1) and D3-A (Channel 2) with 10 μ time divisions.

Figure 18: Voltage at Q1-D (Channel 1) and D3-A (Channel 2) with 5 μ time divisions.

[06-JUN-24] We image the A3050A prototype for record keeping. This version does not include the attenuating switches before the output but still works otherwise.

Figure 19: A3050A LWDAQ Function Generator outside of enclosure, front view.

Figure 20: A3050A LWDAQ Function Generator outside of enclosure, top view.

[24-JUN-24] We construct a +5V PoE DC to DC converter and measure its output current and voltage with different values of R_Sense. Results Below.

Figure 21: A305002B 5V DC to DC converter output for various values of R_Sense.

Figure 22: A305002B 5V DC to DC converter output for various values of R_Sense, zoomed in on end behavior and made x-axis linear.

The 7491199112 PoE Wurth Electronik transformer that we use claims to have a 1.3A saturation current which is consistent with the end behavior of the lower valued R_Sense plots.