[[ coldCLOUD ]]

2013.01 Spartan 3E starter kit

This note is under construction!

Here's a note on how to enable the Spartan 3E starter kit board for analog signal processing using the VHDL language and Xiling ISE Design Suite.

Board

The starter kit board is described in greater details in the user guide and it physically looks like this,

Spartan 3E starter kit board

Components

The main component on the board is of course the Xilinx Spartan 3E field programmable gate array or FPGA. However, in order to do anything sensible with the FPGA we need other components for getting data in and out.

These components are the analog-digital converter (ADC) and its pre-amplifier (Preamp) for reading in the analog signal, and the digital-analog converter (DAC) for writing out the processed data.

The physical location of these components on the board are here marked by dots,

The ADC (red), DAC (green) and Preamp (blue)

PreAmp

Before the analog input signal is digitized by the ADC it enters the programmable preamp from Linear Technology (LTC6912-1). It's a dual channel inverting amplifier with independently programmable gain settings using an 8-bit serial protocol.

The two inverting amplifiers are referenced to $V_{\rm ref} = 1.65 \; V$ and the gain is programmable to 8 discrete settings from 0 to -100. By choosing a specific gain we are basically choosing the input voltage range that may be digitized by the ADC.

Protocol

The 8-bit serial protocol to write the two gain settings may be found in the user guide and it looks like this,

Preamp protocol

Here AMP_CS, SPI_SCK, SPI_MOSI, and AMP_DOUT are the signals to be handled.

Code

These signals may be controlled using this piece of code,

The code creates an entity called SPIBusPreamp and it's driven by an external clock (clkIn), that on rising edges implements the protocol and signals out the instantaneous values for the AMP_CS (CSOut), SPI_SCK (SCKOut), and SPI_MOSI (SDIOut).

The code features a reset function (resetIn) to reset the SPIBusPreamp entity and takes the two 4-bit gain strings as inputs (gain1In & gain2In).

Two additional output ports are implemented. The first is intended for the preamp SHDN (CLROut) lead (see spec sheet), but it's not used here. The other is one intended to signal whether the entity is running (RUNOut).

Please note, AMP_DOUT is just a signal that echoes the previous gain settings and in this context of no interest.

Simulating the behavior of this code results in this,

Simulation of SPIBus_preamp.vhd

Please note, the clock speed and the gain settings used in the simulation are just randomly chosen!

ADC

The ADC is from Linear Technology (LTC1407A-1) and has two differential input ports capable of sampling 14-bit data simultaneously at 1.5 MS/s. Controlling it requires a 34-bit serial protocol.

The ADC is referenced at $V_{\rm ref} = 1.65 \; V$ and accepts input voltages of $\pm 1.25 \; V$ around the reference. When the preamp has a gain of -1 the voltage input range for the ADC is $V_{\rm in} \in [ \, 0.4 , \; 2.9 \, ] \; V$.

Protocol

The 34-bit serial protocol to acquire two 14-bit numbers from the ADC input channels 0 and 1 is found in the user guide and looks like this,

ADC protocol

Here AD_CONV, SPI_SCK, and SPI_MISO are the signal to control.

Please note, there is a latency of one sample - i.e. the converted data from this AD_CONV pulse is first presented in the SPI_MISO signal at the next AD_CONV pulse. Moreover, the two 14-bit numbers are separated two “don't care” bits.

Code

The protocol may be implemented using this code,

The code creates an entity called SPIBusRead and it's driven by an external clock (clkIn), that on rising edges implements the protocol and signals out the instantaneous values for the AD_CONV (CSOut), SPI_SCK (SCKOut), and SPI_MISO (SDOIn).

The i'th bit read off the SPI_MISO (SDOIn) is inserted into the i'th place of the data output signal (dataOut). At the end of the protocol the data output signal holds the two 14-bit numbers.

Again, the code features the reset function (resetIn) and the signal that shows if the entity is running (RUNOut).

Simulating the behavior of this code results in something like this,

Simulation of SPIBusRead entity

Please note, the clock speed and data input used in the simulation are just randomly chosen!

DAC

The DAC is also from Linear Technology (LTC2624) and is a 4-channel 12-bit DAC. Controlling it takes a 32-bit serial protocol.

It's a rail-to-rail DAC and the voltage output runs from $0 \; V$ at bit value zero to $V_{\rm ref}$ at bit value $2^{12}$. The reference voltage is different for the four outputs: outputs A and B are referenced to $3.3 \; V$, while outputs C and D are referenced to $2.5 \; V$.

Protocol

The 32-bit protocol for writing out 12-bit numbers to the four analog outputs is found in the user guide and looks like this,

DAC protocol I DAC protocol II

Here DAC_CS, SPI_SPI_MOSI, SPI_SCK, and SPI_MISO are the signals to be controlled.

The protocol sends the most significant bit (MSB) first - i.e. read the second figure from the right. The command string is specified in the DAC data sheet and should normally be “0011”. The address string selects what output channels to use - string “1111” selects them all.

Please note, the SPI_MISO signal simply echoes the previous output and is not of any interest in this context.

Code

The protocol may be implemented using this code,

The code creates an entity called SPIBusRead that is driven by an external clock (clkIn). On rising edges it implements the protocol and signals out the instantaneous values for the DAC_CS (CSOut), SPI_MOSI (SDIOut), and SPI_SCK (SCKOut).

The entity also takes the data to be written out (dataIn), the DAC command (DACcmdIn), and the DAC address (DACaddrIn).

Again, the code features the reset function (resetIn), a hardware clear function (CLROut), and the signal that shows if the entity is running (RUNOut).

Simulating the behavior of this codes results in something like what is shown below,

Simulation of the SPIBusWrite entity

Please note, the clock speed, DAC command, DAC address, and data input used in the simulation are just randomly chosen!

State Machine

All the essential components are now ready. They just have to be controlled and executed in the right manor. To do this, we instantiate a state machine that takes all signals from the Preamp, ADC, and DAC, and sends them to the right places at the right times.

In principle, all the state machine has to do, is to initialize the preamp at startup, and then forever after read data from the ADC and write data out to the DAC. However, there are many signals that need controlling.

The state machine has four states called ini, amp, read, and write, and follows the flow chart shown below.

State machine flow chart

Code

The code for the state machine is found here,

It instantiates an entity called StateMachine that takes all the output signals from the SPIBusPreamp, SPIBusRead, and SPIBusWrite entities as input. The StateMachine outputs reset signals to all of these entities and the SPI_MISO signal for the SPIBusRead entity.

The job of the StateMachine is to redirect the input/output signals from the correct entity given the current state, and send them to the right board input/output signals - i.e. to signals like SPI_SCK, SPI_MOSI, SPI_MOSI, AMP_CS, AD_CONV, DAC_CS, etc.

The different states involve,

  • ini
    • handling other board signals according to the manual (e.g. some to StrataFlash)
  • amp
    • handling SPIBusPreamp.vhd - i.e. setting the programmable gain
    • this is done a few times to make sure the gain is programmed
  • read
    • handling SPIBusRead.vhd
  • write
    • handling SPIBusWrite.vhd

Clock Operations

The on-board clock is running at 50 MHz. In order to meet the timing requirements of the different components we need to derive clock timings from the on-board clock.

Digital Clock Management

We use the Digital Clock Management (DCM) IP core module from Xilinx to double the on-board clock from 50 MHz to 100 MHz in order to better meet the timing requirements of the ADC and the DAC.

We instantiate an entity named DCM, and use the doubled clock for driving all the components.

Clock Divider

FPGA xc3s500e