Lattice Blog


Interfacing with SPI Devices, Part 1

Interfacing with SPI Devices, Part 1
Posted 09/07/2021 by Eugen Krassin

Posted in

“The LEC2 Workbench” is an ongoing series of technical blog posts focused on application development using Lattice products. The posts are authored by FPGA design experts from the Lattice Education Competence Center (LEC2), the official global provider of training services focused exclusively on Lattice’s award-winning low power FPGAs and solution stacks.

Lattice CrossLink™-NX FPGAs have a rich feature set to accelerate the implementation of high and low speed interfaces. This blog (the first in a two part series) describes the implementation of interfaces to SPI-based external components using CrossLink-NX FPGAs. This first blog describes the implementation of an SPI interface to a DAC (an AD7303 DAC from Analog Devices) using two clock domains. The second blog will describe the implementation of a SPI interface to an ADC (the ADC AD7476 from Analog Devices) using a single clock domain. In both cases, two fundamentally different approaches to implementing the interface are presented. 

Two clock domain implementation (dac_2c)
The AD7303 module from Analog Devices was used as the external DAC. Figure 1 shows the timing diagram of the interface and the timing parameters. In this example, the SCLK frequency is 30 MHz. The timing parameters t4, t5 and t6 are given special attention in the specification of timing constraints and will be used in the set_output_delay constraints.

Figure 1: Timing Diagram and Timing Characteristics 
Figure 1: Timing Diagram and Timing Characteristics

Implementation of the two clock domain solution is shown in Figure 2.

Figure 2: Two Clock Domain SPI Interface Implementation
Figure 2: Two Clock Domain SPI Interface Implementation

Parameters used:
Input Clock Frequency:                    100 MHZ
Internal Clock CLK_120 Frequency:    120 MHZ
Internal Clock CLK_30 Frequency:    30 MHZ
Generated Clock dac_sck: 30 MHZ


The PLL generates two internal, phase-synchronous clocks, CLK_120 and CLK_30, from the external clock CLK (100 MHz).

Module dac_sample_gen
The module dac_sample_gen generates the sample signal (convert) for the dac_fsm. The sample signal initiates the transmission of the digital data to the DAC. The sample rate is set via sample_select [1: 0] signals and is given in Table 1. The block diagram of dac_sample_gen is shown in Figure 3.

Table 1: Sample Rate Settings

Table 1: Sample Rate Settings

Figure 3Figure 3: Block Diagram dac_sample_gen
Figure 3: Block Diagram dac_sample_gen

The mode_select control signal controls the generation of either a square-wave signal or a triangular-shaped signal as input data for the DAC.

Module sync_stage
The dac_sample_gen module works with CLK_120. The control unit dac_fsm is part of the CLK_30 domain. The sync_stage module transports the convert signal from the CLK_120 domain to the CLK_30 domain. Corresponding signals from the dac_fsm are transmitted from the CLK_30 domain to the CLK_120. The block diagram of sync_stage is shown in Figure 4.

Figure 4
Figure 4: Block Diagram sync_stage

Module dac_fsm for two clock implementation
The module dac_fsm controls the generation of the control / data signals to the DAC. In order to adhere to the values of t4, t5 and t6 given in Figure 1, dac_fsm works on the falling edge of CLK_30. Dac_fsm is implemented as a state machine.

Figure 5: Control Structure dac_fsm State Machine
Figure 5: Control Structure dac_fsm State Machine

After the convert signal has been recognized, the bit_count counter is loaded with the value 15. The serial data are output on the dac_sdata line with the falling edge of the clock signal CLK_30. After 16 data bits have been transmitted, dac_fsm de signals readiness again and waits for the next convert signal.

Constraining the Design for the two clock domain solution
1. Constraining the clock CLK
Code Sample 1

2. Constraining of the clocks CLK_120 and CLK_30
There is no need for explicitly specify the clock signals CLK_120 and CLK_30 because there will be automatically defined by the design software. These two clocks are also referred as automatically generated clocks.
Code Sample 2

3. Constraining the dac_clk
The clock signal connected to port dac_sck is a copy of the internal clock CLK_30. This signal is interpreted as a clock by the external DAC. This signal must therefore also be defined as a clock in order to correctly describe the time requirements t4, t5 and t6. This clock is a so-called manually generated clock.
Code Sample 3

4. Constraining the DAC Inputs/FPGA Outputs
Time values t4, t5 and t6 describe the setup / hold requirements for the external module. These requirements are described with the set_output_delay constraint.
Code Sample 4

Running the Timing Analysis for two clock domain solution
The Timing Analysis Report shows the relationship between the two clock signals CLK_120 and CLK_30.

 Timing Analysis Report CLK_120

Timing Analysis Report CLK_30

Note the Clock Domain Crossing Specification from CLK_120 and CLK_30 and vice versa. This is exactly what we expect.
The analysis of the output signal dac_sync and dac_sdata shows the setup and hold slacks achieved based on the set_output_delay specification.

 Output Table


In closing, the two clock domain provides some power consumption advantage because one part of the design is running at lower speed. Furthermore, the timing constraints are easy to specify. This project (dac_2c) is available on request from LEC2. To request a copy, please contact us at

We’ll explore the one clock domain approach in our next blog.

Eugen Krassin is President and Founder of the Lattice Education Competence Center (LEC2).