Here's a simple Verilog example that demonstrates how to interface a potentiometer with an [FPGA](https://www.ampheo.com/c/fpgas-field-programmable-gate-array) using an external SPI ADC (e.g., MCP3008), and display the 10-bit analog value using LEDs or send it via UART.

**Setup Overview**
**Components**
* [Potentiometer](https://www.onzuu.com/category/potentiometers)
* [MCP3008](https://www.onzuu.com/search/MCP3008) (10-bit SPI ADC)
* [FPGA Board](https://www.onzuu.com/category/embedded-complex-logic-fpga-cpld) (e.g., Xilinx or [Intel](https://www.ampheo.com/manufacturer/intel))
* Optional: UART interface / LEDs / 7-segment displays
**MCP3008 Pinout (Important)**
* VDD → 3.3V or 5V
* VREF → Same as VDD
* AGND & DGND → GND
* CH0 → Potentiometer wiper
* DIN (MOSI), DOUT (MISO), CLK, CS → Connect to [FPGA](https://www.ampheoelec.de/c/fpgas-field-programmable-gate-array) SPI interface
**MCP3008 SPI Protocol Recap**
To read CH0:
* Send: 00000001 (Start bit)
* Send: 10000000 (SGL/DIFF = 1, D2-D0 = 000 for CH0)
* Read: 10-bit result (after null bit)
**Verilog Modules Overview**
We'll implement:
1. SPI Master Module
2. MCP3008 Reader
3. Top-Level Module
**1. SPI Master Module (Basic, Mode 0)**
```
verilog
module spi_master (
input clk, // System clock
input start, // Start signal
input [7:0] data_in, // Data to send
output reg [7:0] data_out,
output reg done,
output reg sclk,
output reg mosi,
input miso,
output reg cs
);
reg [3:0] bit_cnt;
reg [7:0] shift_reg;
reg [2:0] state;
localparam IDLE = 0, LOAD = 1, TRANSFER = 2, DONE = 3;
always @(posedge clk) begin
case (state)
IDLE: begin
done <= 0;
cs <= 1;
sclk <= 0;
if (start) state <= LOAD;
end
LOAD: begin
cs <= 0;
shift_reg <= data_in;
bit_cnt <= 7;
state <= TRANSFER;
end
TRANSFER: begin
sclk <= ~sclk;
if (sclk == 0) begin
mosi <= shift_reg[bit_cnt];
end else begin
shift_reg[bit_cnt] <= miso;
if (bit_cnt == 0)
state <= DONE;
else
bit_cnt <= bit_cnt - 1;
end
end
DONE: begin
cs <= 1;
sclk <= 0;
data_out <= shift_reg;
done <= 1;
state <= IDLE;
end
endcase
end
endmodule
```
**2. MCP3008 Reader Module**
```
verilog
module mcp3008_reader (
input clk,
input miso,
output sclk,
output mosi,
output cs,
output reg [9:0] adc_value
);
// SPI wires
wire done;
wire [7:0] data_out;
reg start;
reg [7:0] tx_data;
reg [3:0] state;
spi_master spi (
.clk(clk),
.start(start),
.data_in(tx_data),
.data_out(data_out),
.done(done),
.sclk(sclk),
.mosi(mosi),
.miso(miso),
.cs(cs)
);
localparam IDLE = 0, SEND1 = 1, SEND2 = 2, READ1 = 3, READ2 = 4, DONE = 5;
reg [7:0] rx1, rx2;
always @(posedge clk) begin
case (state)
IDLE: begin
tx_data <= 8'b00000001;
start <= 1;
state <= SEND1;
end
SEND1: if (done) begin
start <= 0;
tx_data <= 8'b10000000;
start <= 1;
state <= SEND2;
end
SEND2: if (done) begin
start <= 0;
tx_data <= 8'b00000000;
start <= 1;
state <= READ1;
end
READ1: if (done) begin
start <= 0;
rx1 <= data_out;
tx_data <= 8'b00000000;
start <= 1;
state <= READ2;
end
READ2: if (done) begin
start <= 0;
rx2 <= data_out;
adc_value <= {rx1[1:0], rx2[7:0]}; // Combine 10-bit result
state <= IDLE;
end
endcase
end
endmodule
```
**3. Top-Level Module (Display on LEDs)**
```
verilog
module top (
input clk,
input miso,
output sclk,
output mosi,
output cs,
output [9:0] leds
);
wire [9:0] adc_value;
mcp3008_reader reader (
.clk(clk),
.miso(miso),
.sclk(sclk),
.mosi(mosi),
.cs(cs),
.adc_value(adc_value)
);
assign leds = adc_value;
endmodule
```
**Simulation and Testing**
* Simulate SPI behavior using a testbench.
* Use a Saleae logic analyzer or [oscilloscope](https://www.onzuu.com/category/oscilloscopes) to verify SPI waveform.
* Turn the potentiometer and observe LED brightness or value changes.
✅ Summary
