Circuit review & bench-test guide
AXS-031 — MCP3008 8-channel ADC PMOD module
Document purpose#
This document explains the axs-031-mcp3008 prototype at component level and turns the design evidence into a practical manual-review and bench-test plan. It is based on the generated schematic (generate_design.py, rev 0.1-schematic, 2026-07-12), the README, and the MCP3004/3008 datasheet.
The board is a design-stage prototype. The schematic is generated and ERC clean (0 errors / 0 warnings) and the netlist has been reviewed, but PCB layout has not started and no board has been fabricated or assembled. There is no first-article bench result of any kind. Every expected value below is a design target to verify, not proof that an assembled board works.
1. What the board does#
The board is a 12-pin PMOD (Type 2, SPI) module carrying a Microchip MCP3008 8-channel 10-bit SAR ADC. VDD and VREF are both tied to the 3.3 V PMOD rail, so full scale is the rail itself. Two onboard teaching loads give immediately twiddleable signals: a 10 kΩ thumb pot whose wiper drives CH0, and a GL5528 LDR / 10 kΩ divider driving CH1. CH2–CH7 plus GND and 3V3 are brought to a 1x8 breadboard header (J2).
It does not include an external voltage reference, input buffering, or anti-aliasing filters. Accuracy is bounded by the 3V3 rail quality.
Functional block diagram#
PMOD J1 (Type 2 SPI) U1 MCP3008 (SOIC-16)
1 ~CS ──<R3 10k pull-up to 3V3>──────> CS/SHDN
2 MOSI ───────────────────────────────> DIN
3 MISO <──── R4 100R series ────────── DOUT
4 SCK ───────────────────────────────> CLK
5/11 GND, 6/12 3V3 ── C1/C2 100n + C3 1u ── VDD = VREF = 3V3
CH0 <── wiper of RV1 10k pot (3V3 .. GND)
CH1 <── junction of R1 (GL5528 LDR, to 3V3) and R2 (10k, to GND)
CH2..CH7 ──> J2 pins 1..6, J2 pin 7 = GND, pin 8 = 3V3
2. Safety and scope boundaries#
- This is a 3.3 V logic module. Never plug it into a 5 V PMOD host or drive any pin from 5 V logic; the MCP3008 absolute maximum for any pin is VDD + 0.6 V, so 5 V signals on a 3.3 V-supplied part violate ratings.
- Analog inputs on J2 must stay within GND to VREF (= 3V3). Inputs between VREF and VDD + 0.6 V merely clip at code 1023; anything beyond the absolute maximum window (−0.6 V to VDD + 0.6 V) risks damage.
- Do not hot-plug the PMOD connector with the host powered if avoidable; PMOD has no defined hot-plug sequencing and misaligned insertion can put 3V3 on signal pins.
- Standalone bench work must use a current-limited 3.3 V supply (set the limit to ~50 mA; the ADC itself draws well under 1 mA).
- An earth-referenced oscilloscope ground clips only to board GND.
- A working readout is not a calibration. VREF is the 3V3 rail, so absolute accuracy is only as good as that rail; do not treat counts as calibrated volts without measuring VREF at the same time.
3. Power and control sequence#
- 3V3 and GND arrive on PMOD pins 6/12 and 5/11. C3 (1 µF) plus C1/C2 (100 nF each on VDD and VREF) provide local decoupling.
- With the host unconfigured or absent, R3 (10 kΩ) pulls ~CS to 3V3, so U1 sits in shutdown/standby (typ. 5 nA, max 2 µA) and never starts a conversion from bus noise.
- The host drives ~CS low, then clocks a start bit, single/diff select, and a 3-bit channel address on DIN. Sampling occurs for 1.5 CLK cycles; conversion takes 10 further clocks, one bit per clock.
- U1 shifts the null bit and the 10-bit result out on DOUT (changing on CLK falling edges); R4 (100 Ω) sits in series between DOUT and the PMOD MISO pin as short-circuit/contention protection.
- ~CS must return high between conversions (t_CSH >= 270 ns).
4. Interfaces and pin maps#
| PMOD pin | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Net | ~CS | MOSI | MISO | SCK | GND | 3V3 | NC | NC | NC | NC | GND | 3V3 |
| J2 pin | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|
| Net | CH2 | CH3 | CH4 | CH5 | CH6 | CH7 | GND | 3V3 |
U1 pin map (MCP3008, SOIC-16): CH0–CH7 = pins 1–8, DGND = 9, CS/SHDN = 10, DIN = 11, DOUT = 12, CLK = 13, AGND = 14, VREF = 15, VDD = 16. AGND and DGND both net to GND on this module.
5. Component-by-component review#
Every reference designator in generate_design.py appears below. #FLG01 and #FLG02 are ERC power-flag pseudo-components on the 3V3 and GND nets; they have no physical footprint and are listed only for completeness.
| Ref. | Part / value | Function and why needed | If absent/open | If shorted, wrong, or misassembled |
|---|---|---|---|---|
| J1 | 12-pin PMOD plug (Type 2 SPI) | Host power and SPI connection; doubled GND/3V3 pins | No power or bus | Offset insertion can put 3V3 onto SCK/MISO; verify keying and orientation |
| U1 | Microchip MCP3008-I/SL, SOIC-16 | 8-channel 10-bit SAR ADC, the entire function of the module | No conversions | Rotated package swaps VDD onto CH pins; a CH-to-CLK solder bridge corrupts every reading |
| RV1 | Bourns TC33X-2-103E 10 kΩ thumb pot | Teaching load: full-rail divider, wiper to CH0 | CH0 floats and reads noise | Wiper open reads erratically; miswired end pins invert the rotation sense but still span 0–1023 |
| R1 | GL5528 LDR (~10 kΩ at 10 lux), MPN TBD | Upper leg of light divider to 3V3 | CH1 is pulled to GND by R2, reads ~0 | Swapped with R2 inverts the light response (bright = low counts) |
| R2 | 10 kΩ 0603 (Yageo RC0603FR-0710KL) | Lower leg of LDR divider; sets the mid-scale light point near the LDR's 10-lux resistance | CH1 floats high through the LDR | Wrong value shifts the whole light-to-counts curve |
| J2 | 1x8 2.54 mm header | Breadboard access to CH2–CH7, GND, 3V3 | No external channels | 3V3 on pin 8 can short to a breadboard rail; unconnected CH inputs float and read noise |
| R3 | 10 kΩ 0603 | ~CS idle pull-up so an unconfigured host cannot start a conversion | ~CS floats; clock noise can clock garbage conversions and raise supply current | Short to 3V3 would fight the host's ~CS driver (~0.33 mA at 3.3 V through 10 k is safe; a 0 Ω error is not) |
| R4 | 100 Ω 0603 | Series protection on ADC-driven DOUT to MISO; limits contention current if the host mis-drives MISO | MISO connects directly; a host contention or hot-plug event stresses DOUT | Too large slows the DOUT edge into bus capacitance; at 100 Ω the added delay is negligible against t_DO = 125–200 ns |
| C1 | 100 nF 16 V X7R (Murata GRM188R71C104KA01D) | VDD decoupling at U1 | Supply bounce during bit decisions raises noise/INL | Short kills the 3V3 rail (host current limit should catch it) |
| C2 | 100 nF 16 V X7R | VREF decoupling; VREF noise converts directly into code noise | Reference bounce scales every reading | Same as C1 |
| C3 | 1 µF 10 V X7R (GRM188R71A105KA61D) | Bulk decoupling; datasheet layout guidance recommends ~1 µF bypass at the device | More rail droop when the host cable is long | Same as C1 |
| #FLG01/#FLG02 | ERC power flags (3V3, GND) | Schematic ERC bookkeeping only | ERC warnings | Not applicable; no physical part |
6. Datasheet summary and design interpretation#
Consulted: Microchip MCP3004/3008 datasheet DS21295D (2008), <https://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf> — also linked from the product page <https://www.microchip.com/en-us/product/MCP3008>.
| Manufacturer fact (DS21295D) | Board-specific interpretation |
|---|---|
| VDD 2.7–5.5 V; I_DD typ 225 µA at 2.7 V / 425 µA at 5 V (550 µA max); standby 5 nA typ, 2 µA max | 3.3 V PMOD rail is comfortably in range; budget well under 1 mA |
| f_CLK max 3.6 MHz at VDD = 5 V and 1.35 MHz at VDD = 2.7 V; only these two corners are specified | At 3.3 V the datasheet gives no dedicated figure. The safe, guaranteed choice is the 2.7 V limit, 1.35 MHz. Linear interpolation (~1.9 MHz at 3.3 V) is plausible but not a specification — treat anything above 1.35 MHz as at-your-own-risk characterization |
| Throughput 200 ksps at 5 V, 75 ksps at 2.7 V, with f_CLK = 18 x f_SAMPLE | At 1.35 MHz SCLK expect up to ~75 ksps sustained; a 24-clock byte-aligned frame gives ~56 ksps |
| SPI modes 0,0 and 1,1 (Section 6.1): DOUT changes on CLK falling edge, host latches on rising edge | Configure the host SPI for mode 0 (CPOL=0, CPHA=0) or mode 3; modes 1 and 2 will sample garbage |
| Minimum effective clock: all 10 data bits must be clocked out within 1.2 ms of the end of the sample period at 85 °C (effective f_CLK >= ~10 kHz), or sample-cap droop degrades linearity | Do not single-step SCLK through a conversion with a debugger; bit-banged hosts must keep the frame fast |
| Transaction: start bit, SGL/DIFF, D2 D1 D0, 1.5-clock sample, null bit, then 10 bits MSB first (LSB-first repeat if clocking continues) | See the exact 3-byte bring-up sequence in Section 9.C |
| LSB = VREF/1024; code = 1024 x VIN / VREF, straight binary; VREF input range 0.25 V to VDD | With VREF = 3V3: 1 LSB ≈ 3.223 mV; the converter is ratiometric to the rail (Section 7) |
| ±1 LSB max INL and DNL, no missing codes; source impedance should be low (Figure 4-2: ~1 kΩ for full speed; higher R_S degrades at high f_CLK) | RV1's worst-case wiper impedance is ~2.5 kΩ and the LDR divider's Thevenin impedance can exceed 5 kΩ in the dark: expect extra error at maximum clock; slowing SCLK or averaging recovers it |
| ~CS must be pulled high between conversions (t_CSH >= 270 ns); analog inputs abs-max −0.6 V to VDD + 0.6 V | R3 enforces the idle state; keep J2 inputs inside the rails |
Check the latest datasheet revision before procurement.
7. Ratiometric behavior versus VREF = 3V3#
Because VREF is the 3V3 rail, counts = VIN / VREF x 1023 (full scale clamps at 1023 = 0x3FF). Consequences worth testing explicitly:
- Rail-referenced sensors track the supply. RV1 is a pure divider from the same rail: its counts depend only on wiper position, not on whether the rail is 3.20 V or 3.40 V. Mid-position reads ~512 regardless.
- Absolute-voltage sources do not. A 1.000 V external reference on a J2 channel reads 1.000/3.300 x 1023 ≈ 310 counts only if the rail is exactly 3.300 V; at 3.25 V it reads ~315. A 1% rail error is a 1% (≈10-count at full scale) reading error.
- VREF noise scales every reading. Ripple on 3V3 appears directly in the codes of absolute sources (and in the LDR reading, since the LDR curve is resistance-based but the divider is rail-driven — its ratio is still ratiometric; only the LDR's resistance-vs-lux is absolute).
- Bench implication: log the measured 3V3/VREF voltage alongside every counts measurement, and compute volts as counts x V_meas / 1023.
8. Expected values before bench testing#
All values assume VREF = VDD = 3.300 V and are design targets, not measured results.
| Quantity | Design target / calculated | What to measure |
|---|---|---|
| Supply current, idle (~CS high) | << 10 µA (standby 2 µA max + leakage) | Bench supply current, standalone context |
| Supply current, converting | 0.2–0.55 mA | Same, while scanning channels |
| LSB size | ≈ 3.223 mV | Computed from measured VREF |
| CH0, pot fully CCW / mid / CW | ~0 / ~512 / ~1023 counts | SPI readout while turning RV1 |
| CH0 mid-position tolerance | 512 ± ~50 (pot linearity, wiper contact) | Same |
| CH1, dark (LDR >= 100 kΩ) | <= ~90 counts (<= 0.3 V) | Cover the LDR |
| CH1, ~10 lux (LDR ≈ 10 kΩ) | ~512 counts (~1.65 V) | Dim room |
| CH1, bright room (LDR ≈ 1–5 kΩ) | ~680–930 counts (2.2–3.0 V) | Desk lighting / phone torch |
| Unconnected J2 channel | Undefined, drifting | Confirm it settles when grounded |
| Grounded J2 channel | 0–1 counts | Jumper CHx to J2 GND |
| J2 channel to 3V3 | 1022–1023 counts | Jumper CHx to J2 pin 8 |
| Max SCLK used in tests | 1.35 MHz (guaranteed corner) | Logic analyzer on SCK |
GL5528 resistance-vs-lux is a loose generic spec (the README flags the MPN as TBD); the CH1 ranges above are sanity bands, not accuracy limits.
9. Manual schematic and assembly review checklist#
- Confirm U1 orientation (pin 1 at CH0) and the -I/SL suffix (SOIC-16).
- Verify VDD (pin 16) and VREF (pin 15) both reach 3V3, AGND (14) and DGND (9) both reach GND; buzz them separately to the PMOD GND pins.
- Confirm C1/C2 land close to pins 16/15 in layout review (layout not yet started — carry this item forward).
- Measure R3 = 10 k from ~CS to 3V3 and R4 = 100 Ω from U1 DOUT to PMOD 3.
- Verify RV1 end terminals go to 3V3 and GND and the wiper to CH0; check rotation direction against silkscreen once layout exists.
- Verify LDR orientation is irrelevant (resistor) but that R1 goes to 3V3 and R2 to GND, junction to CH1.
- Buzz every J1 pin per the Section 4 table, both GND and both 3V3 pins.
- Confirm no solder bridges between U1 pins 10–13 (the SPI cluster).
Ordered bench-test procedure#
Stop at the first abnormal result. Record board serial, host identity, equipment, VREF voltage, and ambient light for CH1 tests.
A. Unpowered inspection and resistance tests#
- Complete the checklist above under magnification.
- Measure 3V3-to-GND resistance both polarities; investigate < 1 kΩ.
- Sweep RV1 end to end and watch CH0-to-GND resistance vary 0–10 kΩ.
- Confirm ~CS-to-3V3 reads ~10 kΩ and MISO-to-U1.DOUT ~100 Ω.
B. First power, no SPI#
Context (a) — PMOD host: plug into a 3.3 V PMOD port on the ECP5 host (ULX3S-class) with the FPGA unconfigured. Context (b) — standalone: wire 3V3/GND from a current-limited bench supply and leave ~CS, SCK, MOSI open.
- Confirm supply current is in the idle band (Section 8); R3 must hold ~CS high (measure it: > 0.9 x VDD).
- Measure VDD and VREF at U1 pins 16/15: equal to the rail within a few mV.
- Probe CH0 while turning the pot: 0 V to rail, smooth.
- Probe CH1 while shading/lighting the LDR: moves in the expected bands.
C. First transaction bring-up (exact bytes)#
Applies to both contexts. In context (a) the byte source is the FPGA SPI master; in context (b) use a lab MCU or adapter (Raspberry Pi Pico, FT2232H, Bus Pirate) at 3.3 V logic. Configure SPI mode 0 (CPOL=0, CPHA=0) — or mode 3 — and SCLK <= 1.35 MHz; start at 100 kHz–500 kHz for bring-up.
Send exactly three bytes with ~CS held low across all three, per datasheet Section 6.1 / Figure 6-1 (single-ended, channel N, N = 0–7):
| Byte | Sent (MOSI) | Received (MISO) | |
|---|---|---|---|
| 1 | 0x01 (seven leading zeros + start bit) | undefined (DOUT high-Z then junk) — discard | |
| 2 | `0x80 \ | (N << 4)` (SGL/DIFF=1, D2 D1 D0 = N, low nibble don't-care) | bits 7..3 undefined, bit 2 = null bit (0), bits 1..0 = result B9 B8 — keep byte2 & 0x03 |
| 3 | 0x00 (don't care) | result B7..B0 |
Result: counts = ((byte2 & 0x03) << 8) | byte3, range 0–1023.
Concrete first transaction — CH0 (the pot): send 0x01 0x80 0x00. With the pot at mid-position expect byte2 & 0x03 ≈ 0x01–0x02 and a total near 512 (e.g. 0x02 0x00 ± tolerance). Pot fully CCW: 0x00, 0x00–0x01. Fully CW: 0x03, 0xFC–0xFF. Then CH1 (LDR): send 0x01 0x90 0x00 and check the Section 8 light bands. A response of all 0xFF means MISO is stuck high (check R4/solder, mode, wiring); all 0x00 with a varying pot means the null-bit alignment or mode is wrong.
Raise ~CS between transactions (>= 270 ns; any inter-byte gap at MCU speeds satisfies this).
D. Channel scan and static accuracy#
- Ground each J2 channel in turn: expect 0–1 counts; tie to 3V3: 1022–1023.
- Feed a known DC voltage (DMM-verified) into one J2 channel; compare counts x VREF_meas / 1023 against the DMM within ±(1% + 2 LSB) as a sanity bound (this board has no calibration claim).
- Repeat at SCLK = 100 kHz and 1.35 MHz; a large difference points at source impedance (Section 6, Figure 4-2 note).
E. Ratiometric demonstration and rail sensitivity#
- Standalone context: vary the bench supply 3.0–3.6 V. CH0 (pot at fixed position) counts must stay constant within a few LSB; an external 1.5 V AA cell on a J2 channel must scale inversely with the rail.
- Log VREF with a DMM at each point and confirm counts = VIN/VREF x 1023.
F. Throughput and host-integration tests#
- Sustained scan of all 8 channels at maximum frame rate; verify no missed frames and stable codes (~56–75 ksps aggregate ceiling at 1.35 MHz).
- In the PMOD-host context, run the eventual HDL SPI master FSM against a logic analyzer capture and check mode, t_SUCS >= 100 ns, and t_CSH.
- EMC, temperature-range, and long-cable testing are out of scope for the first article.
10. Troubleshooting map#
| Symptom | First measurements | Likely areas |
|---|---|---|
| MISO always 0xFF | MISO level with ~CS high, R4 continuity | Mode/wiring, DOUT solder, host pull-up fighting R4 |
| MISO always 0x00 | ~CS reaching U1 pin 10, SCK activity | ~CS stuck high (host not driving), U1 unpowered, mode 1/2 |
| Counts jump ±many LSB | VREF ripple on C2, source impedance | Rail noise, floating channel, SCLK too fast for R_S |
| Pot reads only 0 or 1023 | Wiper continuity at RV1 | Wiper open / end-pin swap with wiper |
| CH1 inverted vs light | R1/R2 placement | LDR and 10 k swapped |
| Works at 100 kHz, fails at 1.35 MHz | t_DO margin at host input, R_S | Marginal timing at 3.3 V (only 2.7 V corner guaranteed), high source impedance |
| Wrong channel data | Byte 2 value on analyzer | Channel bits (N << 4) misplaced |
| High idle current | ~CS voltage | R3 missing/CS driven low continuously |
11. Bench record template#
| Field | Record |
|---|---|
| Board revision / serial | |
| Host context (PMOD FPGA / standalone MCU) and IDs | |
| SPI mode and SCLK used | |
| Measured VREF/3V3 at U1 pin 15 | |
| Idle / converting supply current | |
| First-transaction bytes sent and received | |
| CH0 pot CCW / mid / CW counts | |
| CH1 dark / dim / bright counts and light condition | |
| Grounded and 3V3-tied channel results | |
| Known-voltage channel result vs DMM | |
| Rail-sweep ratiometric result | |
| Deviations, captures, raw-file paths | |
| Reviewer / date / disposition |
12. Review conclusion#
The design is a faithful minimal application of the MCP3008: shared VDD/VREF at 3V3, dual-ground tie, proper decoupling, a ~CS pull-up that keeps the ADC quiet under an unconfigured host, and series protection on the only ADC-driven line. The teaching loads (pot and LDR) give zero-equipment sanity signals. The principal open risks are that no PCB exists yet (layout, AGND strategy, and decoupling placement unverified), the LDR MPN is unpinned so CH1 bands are loose, the 3.3 V maximum clock is not a datasheet-guaranteed corner (use 1.35 MHz until characterized), and absolute accuracy is intentionally limited by using the rail as VREF.