CE433 Spring 2025 Course Project

A new demo video
The project folder used in the demo video above
The .v files and the constraint file used in the demo video

In this project, we are going to build a pre-amplification circuit and a digital sensor to form an all-in-one digital oximeter.

A. The Preamplification circuit

The preamplification can be found in one of my past ENGR337 labs.
Here are more examples on the preamplification circuit:
a. Simple pulse oximetry for wearable monitor
b. NXP's AN4327 example
c. Design of the Pulse Oximetry Measurement Circuit and Its Sensing System Based On CMOS
d. Microchip AN1525 application note
e. A Low cost Oximter

B. Introduction to the XADC (official technical document)
The XADC includes a dual 12-bit, 1 Mega sample per second (MSPS) ADC and on-chip sensors. The ADCs can access up to 17 external analog input channels.



Apart from a single dedicated analog input pair (V P /V N ), the external analog inputs use dual-purpose I/O. These FPGA digital I/Os are individually nominated as analog inputs when the XADC is instantiated in a design. This document refers to these analog inputs as auxiliary analog inputs. A maximum of 16 auxiliary analog inputs are available. The auxiliary analog inputs are enabled by connecting the analog inputs on the XADC primitive to the top level of the design. When enabled as analog inputs, these package balls are unavailable as digital I/Os. It is also possible to enable the auxiliary analog inputs preconfiguration (for example, for PCB diagnostics) through the JTAG TAP



XADC ports



The ADCs have a nominal analog input range from 0V to 1V. In unipolar mode (default), the analog inputs of the ADCs produce a full scale code of FFFh (12 bits) when the input is 1V. Thus, an analog input signal of 200 mV in unipolar mode produces and outputs code of



The ADCs always produce a 16-bit conversion result. The 12-bit data correspond to the 12 MSBs (most significant) in the 16-bit status registers. The unreferenced LSBs can be used to minimize quantization effects or improve resolution through averaging or filtering. The 12-bit unipolar transfer function for the ADCs. The nominal analog input range to the ADCs is 0V to 1V in this mode. The ADC produces a zero code ( 000h ) when 0V is present on the ADC input and a full scale code of all 1s ( FFFh ) when 1V is present on the input.

The analog inputs of the ADC use a differential sampling scheme to reduce the effects of common-mode noise signals. This common-mode rejection improves the ADC performance in noisy digital environments. To take advantage of the high common mode rejection, users need only connect V P and V N in a differential configuration.



Unipolar Input Signals
When measuring unipolar analog input signals, the ADCs must operate in a unipolar input mode. This mode is selected by writing to configuration register 0 (see Control Registers, page 35 ). When unipolar operation is enabled, the differential analog inputs (V P and V N ) have an input range of 0V to 1.0V. In this mode, the voltage on V P (measured with respect to V N ) must always be positive. Figure 2-6 shows a typical application of unipolar mode. V N is typically connected to a local ground or common mode signal. The common mode signal on V N can vary from 0V to +0.5V (measured with respect to GNDADC). Because the differential input range is from 0V to 1.0V (V P to V N ), the maximum signal on V P is 1.5V.



Bipolar Input Signals
The analog inputs can accommodate analog input signals that are positive and negative with respect to a common mode or reference. To accommodate these types of signals, the analog input must be configured to bipolar mode. Bipolar mode is selected by writing to configuration register 0 (see Control Registers ). All input voltages must be positive with respect to analog ground (GNDADC). When bipolar operation is enabled, the differential analog input (V P – V N ) can have a maximum input range of ±0.5V. The common mode or reference voltage should not exceed 0.5V in this case



Our preamplification has a common mode voltage applied to the signal already so the two modes don't make any differences to the circuit connection. Just short GND to VN and short OpAmp output to VP.

The Basys 3 board only has 4 channels of the ADC connected to header pins.



Other AD ports can be identified on the pinout of the XC7A35T - CPG236 device here. More information about the pinout can be found here. Typically, the auxiliary analog inputs are allocated evenly over banks 15 and 35. The following ports are within Bank 35.



It didn't show Bank 15 on this webpage but I saw a bunch of 'A' ports in Bank 14 and they are occupied by buttons and seven segment display modules on the Basys 3 board. 
However, from the Bank 35 snapshot above, channels 6 (XA1), 7 (XA3), 14 (XA2), and 15 (XA4) are available at the header pins.
We can also see corresponding information from the constraint file.



You can see that VP_0 and VN_0 are not in the constraint file. They don't need to be in the constraint file.



C. An Official Example to test
1. Load the 2018.2 version to your board for the first demo


From the official tutorial I found the 2018.2 version on GitHub.

Download and unzip the project folder, locate the project file and double click.



It may ask you about the compatibility issues with your 2018.3 Vivado. They may have some changes to the XADC IP. I chose to update the IP to the 2018.3 version when the window popped up. I'm not sure if it does what I expected.

This project folder contains the .bit file so in Vivado, directly open the hardware management to program the device using the .bit file.





XADC has differential inputs. I used Channel 1 (figure above) for testing purporses. All other pins must be shorted to GND to avoid crosstalk (critical).
The Basys 3 GND is connected to a bread board so the unsed channels can all be connected to the GND rail on the board.
A bench-top power supply output a floating 1V DC to Channel 1 (vauxp 6 and vauxn 6). The Basys 3 board should show 1.000 on the seven segment display and show some LED effects on the leds.





Here are some examples from last year's CE433 course project. Feel free to directly use the code and circuit connection there.

1. tschermer
2. imvanhorn

Let's take a look at things in the top module of the official example.

First, form the instantiation of the xadc module inside the top module, you can tell that the 'end of conversion' (eoc_out) is shorted to 'digital enable input' (den_in) which means that whenever the conversion is done, it sends a pulse to enable the next conversion. vn_in and vp_in are not availale on the Basys 3 board. They are grounded and not used.



You can tell that when 'ready' goes to 1, bits 12 - 15 are used as a counter. It is looking at the top 4 bits of the analog input to determine how many LEDs to be lighten up.



In summary, the XADC module outputs the 16-bit  'do_out' pins and connect them to the 'wire [15:0] data' vector. Only the top 12-bits are ADC data, you can only take the top 8 bits. This will reduce the resolution but will also simplify things.

We can use the SPI follower transmitter module for the FPGA and use Arduino's SPI as the leader receiver.

In the SPI follower transmittermodule, create an 8-bit vector connects to the top 8 bits of the data output from the XADC module.



For physically connecting to the Arduino's SPI pins, you need a level shifter in the middle.



LV is Low Voltage, HV is High Voltage. Connect all the digital pins of the FPGA to the LV side and connect all digital pins of the Arduino to the HV side. 3.3V to LV, 5V to HV, and short the two GND.
On Page 139 of the ATMEGA 328P datasheet, we can find the information about different modes of SPI operation.





The SPI follower transmitter code tells us that data is made available to miso at the falling edge of sck and it expects the leader receiver to take it in at the rising edge of sck. So it should be rising edge sampling in the middle of the data.



Comparing to the SPI modes with the verilog code, the SPI FPGA module is likely running under either Mode 0 or Mode 3.

When you program your Adruino, try to set it under both modes and check which one is sending good results.




---------------------------------------
Tasks:
1. Form a team of 2-3 members, study the preamplification circuit, and prepare a 5-page literature review and report covering the following topics. Ensure to include at least 10 references. (Use 12 pt font size, Times New Roman, and single spacing). (5 points each. 25 points)
a. What is an Oximeter? Provide an explanation of the physics and mathematics involved, written for a general audience.
b. Why are compact Oximeters crucial for healthcare? What problems do they address?
c. What are the components of a commercial Oximeter system? Discuss the amplifiers, sensors, and microcontrollers used in these devices.
d. Which amplification circuit will you use? What are the cut-off frequencies and voltage gains? Discuss the significance of using an integrated ASIC digital oximeter.
e. Append a list of electronic parts and a schematic of your preamplification circuit design. Have all the parts you need in a cart (use either Amazon, Digikey, or Mouser) and ask me to check it out for you.

2. Design a pre-amplification circuit and display the signal on an oscilloscope. (25 points)

3. Design a digital system that includes the XADC and the SPI modules in the FPGA. Display the results from a potentiometer analog input in an Arduino serial monitor. (25 points)

4. Interface your analog output from the amplifier with the digital sensor ASIC (FPGA), plot the results in real-time in the Arduino serial monitor.  10-15 min presentation on Thursday 4/24. (25 points)





References

1. The UMD project
2. ATMEGA 328p datasheet