Chapter 8: Bringing Up the Board for the First Time

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: 

  • Preparing for power-up
  • Checking our circuit's basic functionality
  • Adapting the circuit in case of problems
  • Adding FPGA logic and checking I/O signals

Technical requirements

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.

Preparing for power-up

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.

Supplying power to 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.

Checking our circuit's basic functionality

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

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.

Testing the board power supplies

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

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

Figure 8.3 – Location of C22 on PCB

To check the +1.8 V supply voltage, perform the following steps:

  1. With the digital oscilloscope board powered off and in a static-safe environment, connect the multimeter ground clip to the GND test point on the board.
  2. Turn the multimeter on and set it to the 20 V DC range.
  3. Apply power to the board.
  4. Carefully touch the upper side of C22 with the multimeter probe (as shown in the preceding diagram) and, while holding the probe in place, observe the voltage measurement on the multimeter.

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:

  1. Perform another visual inspection, this time focusing on the components associated with the power supply in question. Attempt to identify whether any of the components are not making contact with solder pads. Check whether the power supply IC was installed with the correct orientation. See whether any solder bridges are present, or whether anything else is amiss with component installation.
  2. Verify that the input to the power supply is at the expected voltage. For example, the +2.5 V and +1.8 V power supplies require +3.3 V as input to the voltage regulator IC. Ensure this voltage is getting to the chip.
  3. Consider the possibility that incorrect components may have been installed at some locations. Make sure each resistor is the expected color – typically black – and that each capacitor is its expected color – typically a tan or brown color.
  4. If you think it is possible that the incorrect values for some resistors or capacitors may have been installed, it might be necessary to remove the questionable components using hot air, and then solder new components that have been freshly removed from their packaging in place of them.

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.

Testing the analog amplifiers

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

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

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

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.

Testing the ADC

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

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:

  1. Double-click the AXI Quad SPI block and select the IP Configuration tab.
  2. The Frequency Ratio value of 16 indicates the ext_spi_clk input is divided by 16, producing a SPI clock rate of 10.4 MHz. This is too high for ADC readback mode. Change the multiplier in the box to the right of Frequency Ratio (to the right of X) from 1 to 10. This will reduce the SPI clock speed to 1.04 MHz.
  3. Click OK.
  4. Save the block diagram.
  5. I experienced a problem with the SPI pin assignment. The SPI SS signal was assigned to the incorrect pin (V17), which prevented the interface from working properly. To fix this problem, add the following line at the end of arty.xdc and save the file:

    set_property PACKAGE_PIN C1 [get_ports spi_ss_io]

  6. Generate the bitstream.
  7. Export the hardware (File | Export | Export Hardware…).
  8. Open the Vitis project you created in Chapter 5, Implementing Systems with FPGAs.
  9. Update the Vitis project hardware with the new definition you just exported from Vivado.

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:

  1. Create a new source file in the Vitis software project named spi.h. Insert the following code into spi.h:

    // 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);

  2. Create a source file named spi.c and insert the following code:

    #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.

  3. Add the following function to the file:

    // 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.

  4. The following function will write a value to an ADC register, read the value back from the register, and return a status value that indicates TRUE if all the steps were successful and the value read matches the value that was written. Add the following code to the spi.c file:

    // 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.

  5. The ConfigureAdc function, with descriptive comments removed, is listed here. This function writes all five ADC configuration registers with hardcoded values and returns a status value indicating whether all the operations were successful:

    // 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;

    }

  6. In the main.c file, add the following line after the other #include statements:

    #include "spi.h"

  7. In the main.c file, at the very beginning of the main function, add the following code:

        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");

  8. Save all the files you have edited. Ensure the spi.h and spi.c files appear in the Vitis Explorer window inside the src folder.
  9. Press Ctrl + B to build the application. Ensure there are no errors.
  10. Start the debugger and run the application.
  11. If the SPI is operating as expected, you should see the following output:

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.

Adapting the circuit in case of problems

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.

Cutting PCB traces

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.

Installing solder jumpers and jumper wires

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

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.

Removing components

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.

Adding components

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

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.

Generating the ADC encoder clock and 1 KHz calibration signal

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:

  1. Open the oscilloscope FPGA project in Vivado.
  2. Open the project block diagram, then double-click the Clocking Wizard block.
  3. Select the Output Clocks tab, then check the box next to clk_out4.
  4. Set the frequency of clk_out4 to 10 MHz and click OK.
  5. Create a new design source file named adc_interface.vhd.
  6. Replace the default content of the new file with the following code and save the file:

    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.

  7. Add the following lines to the arty.xdc file:

    # 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.

  8. Right-click on the block diagram's background and select Add Module….
  9. Select adc_interface in the dialog that appears and click OK.
  10. Connect the clk_out4 output of the Clocking Wizard to the adc_enc input of the newly added adc_interface_v1_0 block.
  11. Right-click each of the outputs of the adc_interface_v1_0 block and make them external.
  12. Right-click each of the three newly added output ports and edit their properties. Remove _0 from the end of each port name.
  13. Generate the bitstream, export the hardware, and import the hardware configuration into the Vitis project.
  14. Rebuild the project and run the application.

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.10 – ADC encoder clock signal

  • The DCO+ and DCO- differential pair contains the output data clock from the ADC. The frequency of this clock is the ADC encoder clock multiplied by 4, which results in a 40 MHz frequency, as shown in the following figure:
Figure 8.11 – DCO bit 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.

Summary

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.