Technical Articles

Designing a Sigma-Delta ADC from Behavioral Model to Verilog and VHDL

By Ali Behboodian, MathWorks and Jeff Miller, MathWorks


Using disparate tools and languages to develop analog mixed-signal ICs makes the design process prone to error, time-consuming, and complicated. Model-Based Design addresses these problems by enabling engineers to complete all design stages in MATLAB and Simulink. By using a Simulink model as the cornerstone of design, teams can test and verify the design at all stages of development, reducing the chances of discovering expensive structural changes or bugs at the implementation stage.

In this article, we use Model-Based Design with MATLAB and Simulink to design a sigma-delta analog-to-digital converter (ADC). Beginning with a high-level behavioral model of the ADC, we elaborate the design and finally, generate synthesizable VHDL code.

The files for this design are available for download. We encourage you to open the Simulink models and explore different aspects of the design.

The Sigma-Delta ADC Converter

Sigma-delta ADC converters are used almost exclusively in applications that require high-resolution output, such as high-fidelity audio or industrial measurements. To achieve the required high resolution, the analog signal must be sampled at rates much higher than the Nyquist rate. In general, the complexity of the circuit design is proportional to the sampling rate. For this reason, sigma-delta ADCs have traditionally been used for sampling low-frequency signals—that is, signals with relatively low Nyquist rates, such as speech in mobile phones.

A sigma-delta ADC consists of an analog and a digital section (Figure 1). The analog section, which includes a sigma-delta modulator, samples the input at a high rate and produces a binary output whose average value over time tracks the analog input. The digital section, which includes decimation filtering, finds the average value by running the output of the sigma-delta modulator through a low-pass decimating FIR filter. Later in this article, we will exploit the binary nature of the filter's input to implement a very efficient filter architecture.

sigma_delta_adc_fig1_w.gif
Figure 1. High-level model of a sigma-delta ADC. Click on image to see enlarged view.

Developing a Behavioral Model

We begin by developing a high-level behavioral Simulink model. The model is in floating point. We use it as a graphical representation of the system and as an executable specification.

The filter in the digital section, designed in MATLAB, is based on the specifications for an Analog Devices AD1877 16-bit sigma-delta ADC. It is a one-stage FIR filter that decimates the signal by a factor of 64, and has about 3,000 taps. We use the following MATLAB script to generate the digital filter:

Decimation_Factor=64;
Passband_Ripple=.006; %dB
Stopband_Attenuation=90; %dB
Fs=48e3;
Passband=21.6e3;  %dB
Stopband=26.4e3; %dB

Input_Sampling_Rate = Decimation_Factor*Fs;
f=fdesign.decimator(Decimation_Factor,'lowpass',Passband,Stopband,...
Passband_Ripple,Stopband_Attenuation,Input_Sampling_Rate);
h=design(f);

Elaborating the Design

At this stage, the behavioral model is not yet suitable for fixed-point FPGA or ASIC implementation. The reason is that the filter is very large and computationally expensive.  As we elaborate the design, we will reduce the filter size to prepare it for implementation. We will then use the binary nature of the input to the filter to make the design even more efficient. Finally, we will convert the numerics to fixed point. The high-level behavioral model will serve as a reference throughout.

Optimizing the Filter Design       

As a one-stage filter with about 3000 taps, our original digital filter requires a significant number of arithmetic operators. Using MATLAB, we break it down into a three-stage decimation filter (Figure 2). Each stage has 40, 12, and 194 filter taps, respectively, and each stage decimates the signal by a factor of 8,2, and 4, respectively, for a total of 64. This approach reduces the total number of coefficients by a factor of about 10, noticeably reducing the number of arithmetic operations required.

sigma_delta_adc_fig2_w.gif
Figure 2. Three-stage filter design.

We compare the frequency response of the original one-stage filter with the new three-stage filter (Figure 3). We see that the magnitude response of the three-stage filter matches the magnitude response of the original one-stage filter very closely.

sigma_delta_adc_fig3_w.gif
Figure 3. Comparison of the one-stage and the three-stage filters. The red lines indicate the specification mask. Click on image to see enlarged view.

In the Simulink environment, we test our elaborated design and verify that it compares well with the behavioral model (Figure 4). Using a multi-rate, multi-stage filter design reduces computational complexity dramatically, but introduces a greater group delay for the filter.  This larger delay is noticeable in the filter output traces shown at the bottom of Figure 4, where the end of the second trace visibly lags behind the end of the first trace because of the greater filter delay.

sigma_delta_adc_fig4_w.jpg
Figure 4. Verifying the three-stage filter design in Simulink. Click on image to see enlarged view.

Elaborating on the First Stage of the Filter

As mentioned above, the first stage is a 40-tap FIR filter. Generally, to implement such a filter we would need 40 multiplications and 39 additions for every output sample. However, as the analog section feeds a binary signal to the first stage of the filter, we can implement the first stage using look-up tables. This method needs no multiplications and only 4 additions.  The other two stages will be implemented in the conventional way.

To understand how we can replace a 40-tap FIR decimation by 8 filter with look-up tables, let’s first look at the simpler case of an 8-tap FIR decimation by 8 filter.  In this case, for every 8 binary input samples, the filter generates one output sample. The output sample depends on the 8 input samples and can take on 256 distinct values (because each sample has only two levels). The look-up table will use 8 binary input samples as an index to a look-up table with 256 precomputed filter outputs. This leads to a very efficient filter design with no multipliers.

Using this approach, we break down the 40-tap filter into 5 segments of 8 taps each.  We generate a look-up table for each segment and combine the 5 look-up table outputs to produce the overall result.  You can download the MATLAB code that we use to generate the look-up tables entries.

Figure 5 shows the final design. The input to the design is a binary signal that is either 1 or -1. Notice that the design uses a downsampling block and an Embedded MATLAB function block. The output of the downsampling block has a rate 8 times slower than the input. Different colors in Figure 5 indicate signals with different rates.

sigma_delta_adc_fig5_w.gif
Figure 5. Efficient design of the first stage of the filter. Click on image to see enlarged view.

With the Embedded MATLAB function block we can bring MATLAB code into Simulink and then simulate the design. Embedded MATLAB can simplify modeling algorithms that are best and most easily represented using text-based modeling. In this case, the MATLAB code is quite simple (Figure 6). 

sigma_delta_adc_fig6_w.jpg
Figure 6. Contents of the Embedded MATLAB function block in Figure 5. Click on image to see enlarged view.

At this point we verify that the design functions properly.  It is best to identify any differences now rather than during subsequent implementation of the filter on hardware. The Simulink model shown in Figure 7 compares the output of the original filter with that of our elaborated filter. We see that there is initially a discrepancy in the output of the two designs, but that the discrepancy goes to zero over time. The reason for the mismatch is the difference between the initial conditions of the original design and those of the elaborated design created using LUTs. We can eliminate the mismatch by setting appropriate initial conditions and placing extra delay blocks.

sigma_delta_adc_fig7_w.jpg
Figure 7. Verification of the elaborated design in Figure 5. Click on image to see enlarged view.

Converting the Model to Fixed Point

So far, all our models have used floating-point arithmetic. For efficient FPGA or ASIC implementation, we must convert our model to fixed point (Figure 8). We use MATLAB and Simulink to convert the filters to fixed point. In the Simulink environment, each arithmetic block can handle both floating-point and fixed-point computations, simplifying the conversion process. We use Simulink to verify that the output of the fixed-point design matches that of the reference design.

sigma_delta_adc_fig8_w.gif
Figure 8. Fixed-point model. Click on image to see enlarged view.

HDL Code Generation

MathWorks tools enable us to generate synthesizable VHDL or Verilog code for the fixed-point, multirate system that includes the filters, the Embedded MATLAB function block, and other blocks used in the digital section of the ADC design. We use Simulink HDL Coder to generate VHDL code from the first stage of the filter shown in Figure 8 and Filter Design HDL Coder to generate VHDL code from the second and third stages. Figure 9 shows part of the VHDL code that we generated from the first stage of the filter.

sigma_delta_adc_fig9_w.gif
Figure 9. Sample of the VHDL code generated using Simulink HDL Coder. Click on image to see enlarged view.

Simulink HDL Coder lets us generate VHDL or Verilog code for different hardware implementations of specific blocks, such as Sum, Product, and MinMax blocks. These different implementations are generally a compromise between speed and chip area. In our example, we use an optional control file to explore alternative implementations for the Sum block shown in Figure 8, using first a Cascade and later a Tree implementation. 

In addition to the VHDL or Verilog code, Simulink HDL Coder can generate a cycle-accurate model that corresponds to the particular implementation choice made for the Sum block. Figure 10 shows the model generated for a Cascade implementation. Figure 11 shows the model generated for a Tree implementation. We can simulate the generated models and verify their output against the reference model.

sigma_delta_adc_fig10_w.gif
Figure 10.  Cascade implementation of the Sum block. Click on image to see enlarged view.
sigma_delta_adc_fig11_w.gif
Figure 11. Tree implementation of the Sum block. Click on image to see enlarged view.

Synthesis Results

Following VHDL code generation, we must prepare the code for hardware implementation. To do this we synthesize the VHDL code that we generated for the first stage of the filter and perform place and route for a Virtex 4 vsx25-10 FPGA using Xilinx ISE software tools. The timing analysis shows that we can run the design at a clock rate of 210 MHz.

Summary

In this article, we used Model-Based Design and MathWorks tools to create a high-level, executable behavioral model of a sigma-delta ADC. We elaborated on the behavioral model to prepare it for hardware implementation on an FPGA. We continuously verified the output of our models throughout the process. This approach enabled us to uncover a discrepancy in the design that could have caused performance problems if left undetected. We used Simulink HDL Coder to generate HDL code from the model and incorporated MATLAB code into the Simulink models using the Embedded MATLAB function block.  An executable model created using MATLAB and Simulink is the cornerstone of this design approach.

Published 2007

View Articles for Related Capabilities

View Articles for Related Industries