fpga4fun.com - where FPGAs are fun.
Home
Welcome
Information


FPGA projects
Music box
Pong game
R/C servos
Text LCD module
Quadrature decoder
PWM and one-bit DAC
Debouncer
LED displays
Crossing clock domains
External contributions

FPGA interface projects
RS-232
JTAG
I2C
EPP
SPI
CNC steppers

FPGA advanced projects
Graphic LCD panel
Digital oscilloscope
10BASE-T interface
PCI interface
Spoc CPU core

Hands-on
A simple oscilloscope


FPGA introduction
What are FPGAs?
How FPGAs work
FPGA pins
Clocks and global lines
Download cables
Configuration
Learn more

FPGA software
Design software
Pin assignment
Design-entry/HDL
Simulation/HDL
Synthesis and P&R

FPGA electronic
SMD technology
Crystals and oscillators

HDL info
HDL tutorials
Verilog tips
VHDL tips

Quick-start guides
ISE
Quartus

Site
News
FPGA links
HDL tutorials
Forum


Digital oscilloscope - part 4

Now that the oscilloscope skeleton is working, it is easy to add more functionality.

Edge-slope trigger

Let's add the ability to trigger on a rising-edge or falling-edge. Any oscilloscope can do that.

We need one bit of information to decide with direction we want to trigger on. Let's use bit-0 of the data sent by the PC.
assign Trigger = (RxD_data[0] ^ Threshold1) & (RxD_data[0] ^ ~Threshold2);

That was easy.

More options

Let's add the ability to control the trigger threshold. That's an 8-bits value. Then we require horizontal acquisition rate control, filtering control... That requires multiple control bytes from the PC to control the oscilloscope.

The simplest approach is to use the "async_receiver" gap detection feature. The PC sends control bytes in burst, and when it stops sending, the FPGA detects it and assert an "RxD_gap" signal.
wire RxD_gap;
async_receiver async_rxd(.clk(clk), .RxD(RxD), .RxD_data_ready(RxD_data_ready), .RxD_data(RxD_data), .RxD_gap(RxD_gap));

reg [1:0] RxD_addr_reg;
always @(posedge clk) if(RxD_gap) RxD_addr_reg <= 0; else if(RxD_data_ready) RxD_addr_reg <= RxD_addr_reg + 1;

// register 0: TriggerThreshold
reg [7:0] TriggerThreshold;
always @(posedge clk) if(RxD_data_ready & (RxD_addr_reg==0)) TriggerThreshold <= RxD_data;

// register 1: "0 0 0 0 HDiv[3] HDiv[2] HDiv[1] HDiv[0]"
reg [3:0] HDiv;
always @(posedge clk) if(RxD_data_ready & (RxD_addr_reg==1)) HDiv <= RxD_data[3:0];

// register 2: "StartAcq TriggerPolarity 0 0 0 0 0 0"
reg TriggerPolarity;
always @(posedge clk) if(RxD_data_ready & (RxD_addr_reg==2)) TriggerPolarity <= RxD_data[6];
wire StartAcq = RxD_data_ready & (RxD_addr_reg==2) & RxD_data[7];

We've also added a 4 bits register (HDiv[3:0]) to control the horizontal acquisition rate. When we want to decrease the acquisition rate, either we discard samples coming from the ADC, or we filter/downsample them at the frequency we are interested in.

More and more features

As you can see, there are lots of features that can be added. The interesting thing is that you can design the oscilloscope the way you need it - maybe a special trigger mechanism? a special filtering function?
Your turn to experiment.




This page was last updated on April 12 2005.