Having designed, constructed, cleaned, and inspected the printed circuit board, it is now time to apply power – in other words, perform the infamous smoke test. This chapter will lead you through the process of carefully providing first-time power to the board and checking basic circuit-level functionality. If you discover any problems, this chapter contains suggested approaches for fixing them. Once the board has passed these tests, we will continue to work on the FPGA logic, and will test the digital interface to the oscilloscope board.
After completing this chapter, you will have learned how to prepare the circuit for initial power application and how to test circuit components for proper operation. You will also understand how to identify and fix problems with the assembled circuit, and will have also checked out the digital interface to the circuit board.
We will cover the following topics in this chapter:
The files for this chapter are available at https://github.com/PacktPublishing/Architecting-High-Performance-Embedded-Systems.
To perform the checkout procedures on the digital oscilloscope circuit board, you will need a multimeter capable of measuring DC voltages. To examine the clock and data signals, you will need an oscilloscope with a bandwidth of at least 40 MHz.
Chapter 7, Building High-Performance Digital Circuits, took us through the steps of constructing, cleaning, inspecting, and performing basic electrical checks on the digital oscilloscope circuit board. We are now ready to apply power to the board and perform testing to determine whether it is operating correctly.
Before applying power to the board, it is important to keep in mind that you need to exercise care when handling it and while it is operating. The integrated circuits on the board remain susceptible to damage from electrostatic discharge (ESD), and it is easy to cause damage when you're probing parts of the circuit with metallic multimeter or oscilloscope probes. It is best to perform this work in an ESD-controlled environment, such as on the mat you use for soldering, and with a wrist strap in place.
If you must work with the board in a non-ESD-controlled environment, you should carefully handle the board by the edges and avoid touching the components on top of the board, the pins on the connectors, and any exposed pins or traces on the bottom of the board.
The board requires +3.3 VDC as its input power source. If you have a standalone power supply that provides this voltage, you may want to use it for the initial power application.
If you do not have a separate power supply, you can use the Arty board to provide power. Our successful electrical check of the board at the end of Chapter 7, Building High-Performance Digital Circuits, indicated that there is substantial resistance between the +3.3 V power pins and board ground, which indicates the risk of shorting the Arty board power supply to ground is minimal.
The initial functionality checks will not require the Arty to perform any actions other than provide power to our board. If you are using a standalone power supply, set the voltage to +3.3 VDC and the current limit to 300 mA, if possible. Connect the +3.3 V and ground lines from the power supply to the board edge pins, as shown in Figure 7.10 in the preceding chapter. You can choose any of the +3.3 V pins to provide power and use any of the GND pins to connect to the power supply ground. Double-check to ensure each of the connectors is on the correct pins.
If you are using the Arty board to provide power for the initial testing, ensure the USB cable is disconnected and that the Arty board is powered off before connecting the digital oscilloscope board to the Arty. Plug the oscilloscope board into the two center Pmod connectors on the Arty board. Make sure both rows of pins are inserted correctly and that the connectors are fully seated. The edge of the digital oscilloscope PCB should be flush against the edge of the Arty board.
The moment of truth has arrived: it is time for the smoke test. This term refers to the unfortunate situation where, sometimes, when a new circuit receives power for the first time, it produces smoke. This is obviously a very bad sign, and if it happens, you should remove power immediately, avoiding contact with the board if possible. If a board is producing smoke, some of the components on it will be very hot, and it is even possible for parts to explode, scattering pieces in a shrapnel-like manner. While such excitement is very unlikely with our 3.3 V circuit, it's always advisable to wear safety glasses during initial testing of a newly built electronic device.
Turn on the power to the board, either by enabling the power supply output (checking again to ensure the voltage is set to +3.3 V first) or by connecting power to the Arty board via the USB cable or through the board's power connector.
Observe the oscilloscope board for a moment. Nothing (such as smoke being emitted!) should be happening. If you are using an Arty to provide power, the red and green LEDs on the Arty should illuminate in their usual manner. If you are using a standalone power supply that displays the current being supplied, it should show a reading between 100 and 200 mA.
We are now ready to check the major subsystems of the circuitry, beginning with the on-board power supply voltages. These steps are the subject of the next section.
With power flowing to the board, we can start checking the DC behavior of the circuitry. This testing can be performed with a standard multimeter set to cover the range -4.0 to +3.3 V, which is typically the 20 V range.
Attach a clip lead to the multimeter's ground connection. Connect the ground clip to the GND test point on the digital oscilloscope circuit board.
Attach a probe-type lead to the multimeter's DC voltage input. This lead should come to a point, which will allow you to accurately contact small target locations on the PCB.
The following photo shows clip- and probe-type multimeter leads:
Figure 8.1 – Clip- and probe-type multimeter leads
We will be using the KiCad circuit schematic and PCB layout diagram to identify specific circuit points for testing with the multimeter. The schematic allows us to easily locate the features of the circuit we are interested in checking. The PCB diagram tells us where to find these points on the board.
When testing points on the circuit with the multimeter probe, it is important to be very careful to only touch the location you intend to examine. It is generally not a problem if you happen to touch the wrong place in the circuit with the probe. This is because the probe has a high impedance that has only a minimal effect on circuit behavior. However, problems arise if you happen to touch two circuit locations with the probe simultaneously. This can easily happen if you are trying to touch a single pin on an IC with closely spaced leads. Causing a short circuit in this manner can instantly destroy circuit components.
If you need to check the voltage on an IC pin, it is better to check some other component that is directly connected to the pin, such as a resistor, a capacitor, or a connector. With a bit of care, it is easy to touch one end of an SMT resistor or capacitor without any significant risk of creating a short to another circuit element.
If you find that you need to test a pin on an IC, it is best to check a pin at one end along the side of the IC, if possible. If you must check a pin that is surrounded by other pins, ensure you have good lighting, use magnification if necessary, and carefully slide the probe up so that it touches the pin. Ensure your hand does not slip while you glance at the meter. Then, carefully pull the probe away from the pin.
The first subject of our testing is the collection of power supply voltages generated on the board. This is the topic of the next section.
First, we will check the power supply voltages that are generated on the board: +2.5 V, -2.5 V, and +1.8 V. Let's begin with +1.8 V. The following diagram is the schematic for the +1.8 V power supply:
Figure 8.2 – +1.8 V power supply
The power supply output voltage, +1.8 V, is available at pin 5 of integrated circuit U2, as well as at the side of capacitor C22, which is connected to U2.
The following diagram shows the location of capacitor C22, along with some of the surrounding components, including U2:
Figure 8.3 – Location of C22 on PCB
To check the +1.8 V supply voltage, perform the following steps:
The voltage measurement should be within a few millivolts of 1.8 V. In my case, the multimeter provided a steady reading of 1.793 V.
Performing similar checks on the +2.5 V and -2.5 V power supplies, which can be accessed at the corresponding test point loops, yielded readings of +2.501 V and -2.506 V on my board, respectively. Your measurements may be slightly different, based on normal component variation. However, your voltages should be within a few millivolts of the target voltage.
If your testing produces similar readings – great! You are ready to move on to the next steps in checking out the board.
If any of the power supply readings differ substantially from the expected voltage – that is, by more than about 10 millivolts – you should stop what you're doing and attempt to resolve the problem. The following steps may be helpful when troubleshooting:
If none of these steps resolve a power supply voltage problem, there may be a cause other than an assembly error. If the current required by the components using the power supply exceeds the supply's capacity, the output voltage will droop. In this situation, it is necessary to return to the drawing board and reengineer the circuit. The circuit redesign must either provide a power supply with sufficient output current or modify the circuit design so that it uses components that draw less current than the capacity of the power supply.
If it turns out that changes need to be made to the circuitry to achieve acceptable performance, it may be possible to make some minor modifications directly to the PCB, without the need to incur the expense and delay associated with revising the circuit board. This type of modification will be covered later in this chapter.
If all the power supply voltages are correct, we are ready to proceed with checking out the remaining functional subsystems of the digital oscilloscope. We will continue by testing the analog amplifiers in the next section.
The oscilloscope input signal enters the board circuitry at the BNC connector, as shown in the following diagram:
Figure 8.4 – Digital oscilloscope input circuitry
Our initial check will use a +2.5 V DC input signal to determine whether the circuity is performing properly. When connected to a stable DC input signal, the capacitors and the gas discharge tube, labeled GDT in the preceding diagram, should have no influence on the voltage at different points in the circuit. The voltage at each point should remain constant.
The resistance of R11 is negligible in comparison to R12 and R13. The resistance of an oscilloscope probe when set to the 1X range (typically 100 to 300 Ohms) is also negligible relative to those two resistors.
With a constant +2.5 V input voltage, and ignoring the resistance of R11 and the scope probe, the expected voltage at the connection point between R12 and R13 can be determined as follows:
Perform a measurement of this circuit location using the procedures described earlier in this chapter. My reading was 0.121 V. If your measurement is not within a few millivolts of the expected value, attempt to identify and fix the problem.
If the voltage measurement is acceptable, the next step is to measure the output of operational amplifier (op amp) U7. U7 is configured as a unity-gain op amp, meaning the amplifier's output voltage is equal to its input voltage. The purpose of U7 is to provide a greater current-driving capability to the differential amplifier (U8) input than is available from the R12/R13 resistor divider network.
The following diagram shows the input and output connections of U7. Resistor R14 provides current limiting protection for U7 in case the input signal is connected to an out-of-range voltage. During normal operation, U7 provides a very high input impedance, which means there is negligible current through R14, and a corresponding negligible voltage drop across R14:
Figure 8.5 – Unity gain op amp
The signal we need to measure is on pin 6 of U7, which is not at the end of a row of pins. Pin 6 connects directly to pin 2, which is also not at the end of a row of pins. We can use the KiCad PCB layout to examine the network of connection points associated with these pins.
In the Pcbnew KiCad application, by performing a Ctrl + left-click on a circuit trace, the selected trace becomes highlighted and shows all of the points connected to it. The following diagram shows the trace connecting pins 2 and 6 of U7, as well as the connections to the input pins of U8. The collection of traces connecting multiple points in a circuit is referred to as a net:
Figure 8.6 – Net connected to pins 2 and 6 of U7
Because the pins on U7 are fairly large, it may be reasonable to carefully measure the pin 6 voltage directly on the IC itself. It is also possible to probe one of the vias that connect the top and bottom traces on this net. In the preceding diagram, the vias are the circles at the connection points between the red top layer traces and the green bottom layer traces. The voltage on U7 pin 6 should match the voltage at the connection between R12 and R13, which is approximately 0.118V.
If the output voltage of U7 is correct, the next steps are to examine the outputs of the remaining amplifiers in the path to the ADC inputs: U8 and U9. Using an approach similar to the one we have used, you should calculate the expected output of each amplifier in response to the input voltage and then measure the output of the amplifier. U9 is a differential amplifier with an output voltage centered at the ADC input common mode voltage of 0.9V.
So far, our circuit check has verified that our amplifiers operate properly, up to the point of generating the differential signal that serves as the input to the ADC. The next step is to test the ADC itself.
The LTC2267-14 dual-channel ADC operates with a +1.8 V power supply. Although the device has two input channels, this design uses only one of them. This approach permits straightforward expansion of the design to support two oscilloscope input channels in the future. Using a Serial Peripheral Interface (SPI) configuration setting, the second ADC channel will be placed into nap mode to minimize power consumption.
The ADC has three major interfaces to other circuit components:
Having verified that the analog output of the differential amplifier is performing as expected, we assume for the time being that the ADC will receive that input. We will need to add some FPGA code to drive the high-speed digital interface from the ADC to the Arty board later in this chapter.
We can now begin to interact with the SPI configuration port on the ADC. To do this, a 6-pin ribbon cable is required to connect the SPI port on the Arty board to the SPI port on the oscilloscope board. Ensure that the pin 1 end of each cable is connected to the proper side of the connector. Both boards have a number 1 on them, indicating the location of pin 1. The type of cable required for the SPI connection is shown in the following figure:
Figure 8.7 – SPI connection cable
To use SPI to communicate with the ADC, we will continue developing the application we started in the Kicking off the oscilloscope FPGA project section of Chapter 5, Implementing Systems with FPGAs.
The first step working with the SPI connection is ensuring it is operating at a suitable clock speed. From the LTC2267 data sheet (available at https://www.analog.com/media/en/technical-documentation/data-sheets/22687614fa.pdf), we can see that in write mode, the SPI supports a clock period of 40 ns (25 MHz), while in readback mode, it supports a minimum clock period of 250 ns (4 MHz). Referring to the block diagram for our FPGA design, the ext_spi_clk input to the AXI Quad SPI block is driven by the 166.66667 MHz output of the Clocking Wizard block.
Before we can begin to use the SPI, we must perform the following steps to adjust the clock speed of the FPGA SPI and to fix separate a problem with SPI pin assignment:
set_property PACKAGE_PIN C1 [get_ports spi_ss_io]
The Board Support Package (BSP) software provided in the Vitis project contains a driver for the Arty SPI interface. We will use this driver to perform communication between the application software and the ADC over SPI.
The LTC2267-14 ADC provides read and write access to five 8-bit internal registers, numbered 0–4. Details on these registers are available in the LTC2267-14 data sheet.
Register 0 is used exclusively for performing a software reset, which is triggered by writing a 1 to register bit 7. This reset must be the first step in the configuration process.
Registers 1–4 contain various configuration settings. Each of these registers can be read or written to at any time. Our code will perform a software reset via register 0 and then write configuration data to each of the four remaining registers. Once each register has been written, it will be read back and the received value will be compared to the value that was just written. Any mismatches during this comparison will result in a failed return status from the configuration routine.
To configure the LTC2267-14 via SPI, perform the following steps:
// SPI interface to LTC2267 ADC
// SPI clock is 166.66667 MHz / (16 * 10) = 1.042 MHz
// LTC2267 max SPI clock speed (readback) is 4.0 MHz
// Configure SPI interface; Return TRUE if successful
int InitSpi(void);
// Returns TRUE if the value was successfully written
// to and read back from the register at reg_addr
int SpiWriteAndVerify(u8 reg_addr, u8 value);
// Pass hard-coded configuration data to the ADC via
// SPI and return TRUE if successful
int ConfigureAdc(void);
#include <xspi.h>
#include "spi.h"
static XSpi SpiInstance;
// Configure SPI interface; Return TRUE if successful
int InitSpi(void) {
int result;
result = XSpi_Initialize(&SpiInstance,
XPAR_SPI_0_DEVICE_ID);
if (result != XST_SUCCESS)
return FALSE;
result = XSpi_SelfTest(&SpiInstance);
if (result != XST_SUCCESS)
return FALSE;
result = XSpi_SetOptions(&SpiInstance,
XSP_MASTER_OPTION | XSP_MANUAL_SSELECT_OPTION);
if (result != XST_SUCCESS)
return FALSE;
result = XSpi_Start(&SpiInstance);
if (result != XST_SUCCESS)
return FALSE;
XSpi_IntrGlobalDisable(&SpiInstance);
return TRUE;
}
The InitSpi function initializes the XSpi driver, performs a self-test on the FPGA SPI hardware, and configures the interface to manually assert the SS signal. This SS mode is necessary for the interface to support the requirements of the ADC SPI. The final steps start the SPI and disable interrupts from the SPI device.
// Send one byte to, or read one byte from the ADC
// Valid values for cmd: 0x00 = write, 0x80 = read
static int do_transfer(u8 cmd, u8 reg_addr,
u8 output_value, u8 *input_value) {
u8 out_buf[2] = { cmd | reg_addr, output_value };
u8 in_buf[2] = { 0 };
const int buf_len = 2;
u32 select_mask = 1;
// Valid commands: 0x00 = write, 0x80 = read
int result = XSpi_SetSlaveSelect(&SpiInstance,
select_mask);
if (result == XST_SUCCESS) {
result = XSpi_Transfer(&SpiInstance, out_buf,
in_buf, buf_len);
*input_value = in_buf[1];
}
return (result == XST_SUCCESS) ? TRUE : FALSE;
}
The do_transfer function will transfer one byte into an ADC register or read one byte from a register, depending on the value of the cmd variable.
// Returns TRUE if the value was successfully written
// to and read back from the register at reg_addr
int SpiWriteAndVerify(u8 reg_addr, u8 value) {
const u8 write_cmd = 0;
const u8 read_cmd = 0x80;
u8 input_value;
int result;
switch (reg_addr) {
case 0:
// The only valid value for reg 0 is 0x80
result = (value == 0x80) ? TRUE : FALSE;
if (result == TRUE)
result = do_transfer(write_cmd, reg_addr,
value, &input_value);
break;
case 1:
case 2:
case 3:
case 4: {
result = do_transfer(write_cmd, reg_addr,
value, &input_value);
if (result == TRUE) {
result = do_transfer(read_cmd, reg_addr, 0,
&input_value);
xil_printf("Value read back %02X\n",
input_value);
if (value != input_value)
result = FALSE;
}
break;
}
default:
result = FALSE;
}
return result;
}
In the SpiWriteAndVerify function, register 0 is handled as a special case. For registers 1–4, the code transfers the value into the register, reads the register, and returns the result of the comparison.
// Pass hard-coded configuration data to the ADC via
// SPI and return TRUE if successful
int ConfigureAdc(void) {
const u8 reg0 = 0x80;
const u8 reg1 = 0x28;
const u8 reg2 = 0x00;
const u8 reg3 = 0xB3;
const u8 reg4 = 0x33;
xil_printf("Register 0: Writing %02X\n", reg0);
int result = SpiWriteAndVerify(0, reg0);
if (result == TRUE) {
xil_printf("Register 1: Writing %02X\n", reg1);
result = SpiWriteAndVerify(1, reg1);
}
if (result == TRUE) {
xil_printf("Register 2: Writing %02X\n", reg2);
result = SpiWriteAndVerify(2, reg2);
}
if (result == TRUE) {
xil_printf("Register 3: Writing %02X\n", reg3);
result = SpiWriteAndVerify(3, reg3);
}
if (result == TRUE) {
xil_printf("Register 4: Writing %02X\n", reg4);
result = SpiWriteAndVerify(4, reg4);
}
return result;
}
#include "spi.h"
if (InitSpi() == TRUE) {
xil_printf("InitSpi success\n");
if (ConfigureAdc() == TRUE)
xil_printf("ConfigureAdc success\n");
else
xil_printf("ConfigureAdc failed\n");
} else
xil_printf("InitSpi failed\n");
InitSpi success
Register 0: Writing 80
Register 1: Writing 28
Value read back 28
Register 2: Writing 00
Value read back 00
Register 3: Writing B3
Value read back B3
Register 4: Writing 33
Value read back 33
ConfigureAdc success
Successfully completing this test indicates that the ADC integrated circuit is powered up and that the SPI interface connecting it to the Arty is working properly.
If you experience issues while checking out a new circuit design that can't be resolved by fixing errors that were introduced during assembly, it may turn out there are higher-level problems with the circuit's design. If the circuit requires fixes involving modifications to component connectivity, it may be possible to make some changes directly on the board and avoid the need for an immediate PCB revision. These techniques are the subject of the next section.
In Chapter 7, Building High-Performance Digital Circuits, we discussed various techniques for repairing problems resulting from improper assembly of the circuit board. The base assumption behind those procedures was that the circuit design was correct, and that any issues that arose were related to the assembly process.
You may reach a point where you identify one or more problems with the design of the circuit itself during testing. Once a design problem has been identified, it might be straightforward to revisit the circuit schematic and make the necessary corrections. The immediate problem, though, is that the PCB you are working with cannot be fixed as easily. Ordering a revised board will cost money and take time. It may be helpful to explore the possibility of modifying the PCB in order to implement immediate design changes.
Depending on the specific problem, it may be possible to make some modifications to the circuit board that will enable continued checkout of the remaining board capabilities. The modifications we will discuss in this section should only be performed on boards that are being evaluated by system developers. In general, due to the fragility of these alterations, boards with these changes should not be released for use by end users of the device.
The types of modifications we will discuss are cutting PCB traces, installing solder jumpers and jumper wires, removing components, and adding components.
If you decide that a trace connecting two points on the circuit should not be there, you can cut through the copper layer to break the connection between those points.
Use a razor knife or hobby knife to make the cut. Apply moderate pressure and make several strokes across the trace. Make sure you do not cut any adjacent components or traces. Once you've finished the cut, use your multimeter to test the resistance between the two points to ensure the trace is fully severed. If the cut ends of the traces connect indirectly through other circuit components, the measured resistance may not be infinite, even if the trace has been fully cut.
Important note
Use caution when working with a sharp knife: When cutting PCB traces, ensure the PCB is on a solid surface and does not wobble. Be very careful not to cut yourself or anything else, such as your work surface. Make sure your first aid kit is handy in case of an accident.
If cutting the trace was the only modification needed, you can now get back to testing the circuit with the trace no longer providing connectivity between its endpoints.
Typically, after cutting a trace, you will need to make connections between other points on the circuit board to correct the design error. This is the subject of the next section.
If you need to make a connection between two points on the PCB that are not currently connected, the first step is to examine the board and identify the available points where each trace or device pin is directly accessible.
If the points you need to connect are very close together, perhaps two adjacent pins on an IC or two resistors located very close to each other, you may be able to connect the points using a solder jumper. A solder jumper is just a lump of solder large enough to span the distance between the two points being connected. A solder jumper is the same thing as a solder bridge, as discussed earlier, except the solder jumper is intentional rather than undesired.
As always, use a sufficient amount of flux to ensure good flow and adhesion of the solder to the metal of the pads and components. A nice thing about solder jumpers is that if you decide you don't want the jumper at a later time, it is easy to remove using a soldering iron, flux, and solder wick.
If the distance to be bridged is greater than a reasonably sized solder jumper can connect, you will need to use a piece of wire to make the connection. If the jumper wire is a connection between points with no exposed pads or components between them, it may be reasonable to use wire that has no insulation. If the wire must cross metal pads and wind around components, the use of insulated wire may be mandatory.
Use a wire thickness that is appropriate for the connection endpoints and the current flow requirements. Jumper wire that attaches to the smallest SMT components should be of suitable fineness for connecting to such small points. If the wire is too thick, it will be difficult to attach to the desired location without coming into contact with other parts of the circuit.
The following photo shows a jumper wire, constructed from a bit of wire clipped from a through-hole resistor, connected between pins 3 and 4 of U4 on an earlier revision of the digital oscilloscope PCB:
Figure 8.8 – Jumper wire connected across IC pins
If at all possible, use the location of a through-hole component, such as a board edge connector, as the connecting point for jumper wires. It is relatively easy to solder a wire to these parts where they pass through the PCB.
The trickiest type of jumper wire connection may be soldering the wire directly to a PCB trace. To do this, first scrape a sufficient amount of solder mask from the trace to expose an area large enough to make a good solder connection. Using flux, solder the jumper wire directly to the trace.
You can expect the jumper wire connections that are made using the methods described in this section to be quite fragile. Handle the board carefully to avoid breaking the wires free from their connections or causing more serious problems, such as lifting components or traces from the PCB surface.
If you suspect an IC is drawing more current than anticipated, and thereby causing an associated power supply voltage to droop, a quick way to test for this is to remove the component from the board and check the supply voltage again. If the supply voltage is now at the expected value, you have your answer.
It may also be the case that a component is interfering with the operation of some other part of the circuit in other ways. By selectively removing resistors, capacitors, and ICs, you may be able to continue checking out portions of the circuit other than the area you have discovered is not operating correctly.
If you discover the circuit is missing a necessary component, it may be possible to install the missing part so that you can continue checking out the circuit. If the missing part is a resistor or capacitor, it will likely be easier to install a through-hole component than an SMT component.
During early revisions of the digital oscilloscope PCB, I discovered that a missing 2.7K Ohm pullup resistor was causing the SPI interface to not work. The requirement for this resistor is clearly identified in the LTC2267-14 data sheet, but I overlooked it.
To get the SPI interface working and to continue the checkout process for the other board functions, I soldered a through-hole resistor to the board connectors, as shown in the following photo:
Figure 8.9 – Pullup resistor soldered to the PCB
Once any problems with the PCB have been at least temporarily resolved, the next step is to generate output signals from the FPGA so that we can drive the inputs to the oscilloscope board. This is the topic of the next section.
Adding FPGA logic and checking I/O signals
In this section, we will add the portion of the FPGA logic that generates signals that drive functions on the digital oscilloscope board. These signals include the 1 KHz calibration signal that is available on one of the board's test points and the ADC encoder clock, which drives the ADC.
Continuing with the Vivado block diagram project for the digital oscilloscope we created in Chapter 5, Implementing Systems with FPGAs, and worked with previously in this chapter, we will now add logic to the FPGA design that will generate the ADC encoder clock and the 1 KHz output signal at the corresponding test point on the circuit board.
To minimize the bandwidth requirements for testing the board with an oscilloscope, we will temporarily reduce the ADC encoder clock frequency, which is intended to be 100 MHz. The ADC will accept a frequency as low as 5 MHz (per the LTC2267-14 data sheet) and operate the ADC at this slower rate. However, the lowest frequency we can readily generate from the Clocking Wizard is 10 MHz. We will set the ADC encoder clock frequency to 10 MHz for the time being.
Perform the following steps to make this frequency change and add the signals to the project:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library UNISIM;
use UNISIM.vcomponents.all;
entity adc_interface is
port (
adc_enc : in std_logic;
enc_p : out std_logic;
enc_n : out std_logic;
clk_1khz_out : out std_logic
);
end entity;
architecture Behavioral of adc_interface is
signal clk_1khz : std_logic;
begin
process(adc_enc) is
variable count : integer := 0;
constant clk_1khz_period : integer := 10 * 1000;
begin
if (rising_edge(adc_enc)) then
count := count + 1;
if (count >= (clk_1khz_period / 2)) then
clk_1khz <= NOT clk_1khz;
count := 0;
end if;
end if;
end process;
CAL_1KHZ_OBUF : OBUF
generic map (IOSTANDARD => "LVCMOS33")
port map (
I => clk_1khz,
O => clk_1khz_out
);
ADC_ENC_OBUFDS : OBUFDS
generic map (IOSTANDARD => "TMDS_33")
port map (
O => enc_p,
OB => enc_n,
I => adc_enc
);
end Behavioral;
The preceding code receives the ADC encoder clock (adc_enc) that was produced by the Clocking Wizard (currently set at 10 MHz) and divides it to produce a 1.0 KHz signal. This 1.0 KHz signal is passed to the clk_1khz_out output using an output buffer (OBUF) driving a 3.3 V CMOS signal. The ADC encoder's output drives a differential signal pair (enc_p, enc_n) using the 3.3 V TMDS I/O standard (OBUFDS).
The Arty board's I/O signal configuration does not support the use of LVDS (the ADC's serial interface standard) on Pmod connectors, but it does support the Transition-Minimized Differential Signaling (TMDS) standard on those pins. TMDS is a high-speed serial data transmission standard similar in many ways to LVDS.
For our purposes, the main difference between LVDS and TMDS is that TMDS generates digital pulses by pulling the voltage down a few hundred millivolts from +3.3 V, while LVDS uses a lower common-mode voltage, about which it generates voltage pulses of a similar amplitude. To interface between LVDS and TMDS, we must accommodate the difference in common mode voltage between the two standards.
Our design uses DC blocking capacitors on each of the four differential signals leading to the Pmod connectors isolating the common mode voltage on each side of the capacitor. The Pmod connector side of these signals also has a 50 Ohm pullup resistor on each line, as required by the TMDS standard. This configuration enables bridging between the TMDS and LVDS I/O standards.
# Pmod Header JC
set_property IOSTANDARD TMDS_33 [get_ports enc_p]
set_property PACKAGE_PIN U12 [get_ports enc_p]
set_property IOSTANDARD LVCMOS33 [get_ports clk_1khz_out]
set_property PACKAGE_PIN T13 [get_ports clk_1khz_out]
These statements include constraint information for the enc_p signal, but they do not mention the enc_n signal. This is because Vivado infers the need for the enc_n signal from the code in adc_interface.vhd and automatically assigns it to the correct pin with the appropriate properties.
Once you've completed these steps, you can use an oscilloscope to examine the differential signal pairs involved in data transfer from the oscilloscope board to the Arty. To do this, you will need to refer to the PCB layout in KiCad and identify the appropriate connector pins or other circuit locations available for probing each of the following signal pairs:
Figure 8.10 – ADC encoder clock signal
Figure 8.11 – DCO bit clock signal
If all these checks have produced satisfactory results, we have successfully demonstrated that almost all of the analog and digital subsystems on the digital oscilloscope board are operating properly. The only remaining untested area of functionality is the ADC conversion of analog inputs into digital outputs. We will work on this aspect of the oscilloscope in the next chapter.
This chapter led you through the process of carefully providing first-time power to the board and checking basic circuit-level functionality. After passing those tests, we added some FPGA code to generate the output signals that drive the oscilloscope board. We also discussed some ways we can modify and adapt the circuit if it turns out to not be functioning as intended.
Having completed this chapter, you now know how to prepare the circuit for initial power application and how to test circuit components and subsystems for proper operation. You have learned how to drive FPGA output signals and understand how to modify and adapt the circuit in case of design problems.
The next chapter will expand on the digital oscilloscope execution algorithm, including the remaining FPGA implementation, the firmware running on the MicroBlaze processor, and the software application running on the host computer.