ADC accuracy test in Altera MAX 10 FPGA

Как известно, Altera относительно недавно начала выпускать новые FPGA, особенность которых — наличие встроенного АЦП. До этого никто не делал аналого-цифровые FPGA. Максимальное достижение — были аппноты как сделать АЦП на внешнем резистивном ЦАП-е или используя LVDS приемник в качестве компаратора (sic!). Меня сразу понравилась такое решение, потому что появляется возможность делать сложные быстродействующие системы управления всего на одной микросхеме. Помимо АЦП, там достаточно памяти RAM и ячеек чтобы воспользоваться софт-процессором NIOS. Кроме того, этот девайс как-бы CPLD — конфигурационная память находится внутри.

Я решил заказать плату BEMICROMAX10, как самую дешевую из всех. К сожалению, возникла удивительно анекдотичная ситуация, подробности которой я опущу, но в результате мне пришлось заполнить и отослать пару формальных бумаг.

Кроме того, поддержка MAX 10 появилась только в Quartus 14, который ставится только на 64-битные операционные системы.

На Aleterawiki есть пример проекта использования АЦП совместно со встроенным термодатчиком. Поскольку сам пример был на VHDL, то я тут же решил сделать minimal working example на Verilog.

Что выяснилось при подготовке исходников:
– Все это дело генерируется с помощью Qsys, стандартный интерфейс с АЦП – шина Avalon. Однако, на самом низком уровне обращения к АЦП, интерфейс представляется такой диаграммой (из даташита):
ADC_Timings

– Тактовый сигнал АЦП сделан аппаратно так, что надо задействовать определенные pll – иначе проект не соберется. В примере было сделано так (картинка из RTL netlist viewer):
ClockTree

– Забавно, но из-за проблем с разводкой (как написано в комментариях к исходникам), коды для переключения каналов входного аналогового мультиплексора идут не последовательно, поэтому вместе с ADC wrapper автоматически вставляется модуль перекодировщика.

Короче, я не использовал Qsys вообще (не хотелось заморачиваться с шиной Avalon и прочим) – просто взял по минимуму исходники из проекта с термодатчиком (chsel_code_converter_sw_to_hw.v, fiftyfivenm_adcblock_top_wrapper.v, fiftyfivenm_adcblock_primitive_wrapper.v), подсмотрел как сделаны соединения и выставил параметры – и сделал все точно также.
В результате получилось непрерывное преобразование из одного фиксированного аналогового входа со скоростью 1 MSPS. Вот можно скачать проект для Quartus: https://sites.google.com/site/akpc806a/ADCTest.qar?attredirects=0&d=1

Результаты:
1. Диапазон входного измеряемого напряжения от 0 до 2.3V при опорном напряжении 2.5V

2. Диапазон кодов примерно от 100h до FA0h. Вот картинка характеристики напряжение-код:
Code_vs_v
(на линейность я специально не проверял – это просто картинка, показывающая диапазон входных напряжений и кодов АЦП)

3. Далее я измерил шум АЦП для нулевого входного напряжения. Просто замкнул джампером на землю аналоговый вход на плате. Собрал 1024 отсчетов АЦП. Вот график:
Code_0

Среднее значение: 277.39
Среднеквадратичное отклонение: 2.10

4. Наконец, я подключил переменный резистор и выставил значение, близкое к концу шкалы. Также отобрал последовательно 1024 отсчетов. Картинка:
Code_full

Среднее значение: 3970.32
Среднеквадратичное отклонение: 2.39

Интересно посмотреть на гистограмму распределения значений АЦП:
Fig_Hyst

Как видно, полученное далеко от нормального распределения. В принципе, это может быть объяснено разными факторами: наводки на длинные провода, переменный резистор большого сопротивления и т.д. Что все на самом деле смазывает чистоту эксперимента).

Большинство значений попало в интервал 3967…3973, что указывает на то, что два младших бита – явно не значащие. Интереснее вычислить соотношение сигнал-шум (SNR). Для постоянного сигнала можно записать такую формулу в дБ:

SNR = 20 \log_{10} \dfrac{mean}{stdev}

Получаем SNR = 64.42. Если пересчитать в количество эффективных бит SNR = 6.02 n + 1.76, то получится n = 10.4
Таким образом, анализ показывает что разрешение АЦП оказывается порядка 10 эффективных бит.

5. Для исследования быстродействия на один из выводов выводился сигнал прямоугольной формы, который далее измерялся с помощью АЦП. Выяснилось, что в плате BEMICROMAX10 по аналоговым входам стоят конденсаторы 0.1 мкФ. Поэтому ни о каком быстродействии говорить не приходится. Пришлось заменить на 25 пФ. В результате получилось действительно быстрое преобразование — правильный результат на выходе АЦП появляется на следующем такте, спустя 1 мкс после изменения входного сигнала. Вот картинка из SignalTap:

Dynamic_edge

Вывод.
Конечно, АЦП в MAX 10 не самый крутой. Он скорее типично “микроконтроллерного” уровня, как по скорости, так и по точности. Однако, для ряда применений реального времени сборка FPGA+АЦП – отличное решение, как например в управлении электродвигателями. Я опробую в самое ближайшее время в качестве контроллера шаговика с цифровым регулятором тока.
Это пока первое подобное решение на рынке – будем надеяться, что увидим еще более крутые аналого-цифровые АЦП от Альтеры.

13 thoughts on “ADC accuracy test in Altera MAX 10 FPGA

  1. Идея мне понравилась – уйти от Qsys вообще и от шины Avalon.
    Я попробовал перенести проект в ПЛИС 10M08SAE144C8G, но не получилось, т.к. в этой м/с один PLL, а в проекте задействовано два PLL. Вот сообщение об ошибке:
    ID:176394 Can’t fit 2 PLLs in the device — only 1 PLLs are available
    Можно ли переделать проект под один PLL?
    Как связаться с автором статьи?
    С уважением, Александр

    • Короче, насколько я понел из того что я сам с этим делал. Там для АЦП надо 10 МГц.
      Я собрал сейчас на 10M08SAE144C8GES с одним ПЛЛ и 50 МГц входом. К сожалению нет возможности протестировать на железе, но из тайминг-анализа и RTL-вьювера вроде похоже на правду. Вот изменения в коде:

      module ADCTest
      (
      clk, // should be 50 MHz !
      leds
      );

      input clk;
      output [7:0] leds;

      reg [31:0] iDiv = 0;

      wire clk_50MHz = clk;
      wire clk_10MHz;

      fingertemp_pll_altpll adc_pll
      (
      .areset(0),
      .clk(clk_10MHz),
      .inclk(clk_50MHz),
      );

      • Здравствуйте!
        К Вашему тексту я добавил в конце “endmodule” и сохранил файл как ADCTest.v
        Пины поменял как надо для платы Altera_10M08S_E144_eval.
        Трансляция прошла успешно, но все 5 имеющихся на плате светодиодов горят ровно. Я рассчитывал, что из-за шума младших битов должна быть какая-то реакция на светодиодах. А может на светодиоды Вы подаете старшие биты? Попробовал подать напряжение 1.65В на первый канал. Никакой реакции. А может не первый канал?
        Все свои программы я писал на AHDL. К сожалению, язык Verilog я не знаю. Планирую в будущем его изучать, но это нужно много времени. Если дадите графический файл, то будет понятна логика работы светодиодов и выбранный канал АЦП. Может тот текст, который Вы дали, является фрагментом программы, а не весь файл?
        А может программа не работает по каким-то совсем другим причинам? Я только начал осваивать МАХ10 – меня привлек АЦП и все остальные отличные ресурсы МАХ10. Раньше я работал с ЕРМ1270Т144, ставил внешний АЦП, использовал язык только AHDL. С МАХ10 опыта пока нет.
        Я буду очень благодарен, если Вы посмотрите мой проект, что в нем не так? Я поместил архив на свой сайт, его можно скачать по ссылке (в архиве также приложена схема платы). Спасибо!
        http://www.aljuel.eu/Archive6/ADCTest_restored.zip

        PS! Если можно, скажите пару слов о себе и этом сайте – это просто для ориентации (немного путаюсь, не совсем понятны цели и интересы). Я хотел поставить лайк “нравится” и сразу увидел необходимость регистрации. Обычно это отпугивает. На своем сайте (www.aljuel.eu) я разрешаю смотреть что угодно и скачивать все что угодно без всякой регистрации (я знаю, демократичный стиль нравится людям). На моем сайте не только реклама, но и документация на мою продукцию, а также и обучение.

    • Нет, это не полный текст. Это то, что надо было изменить 🙂 Я кину сейчас вам полный проект.
      Кстати, может быть там есть примеры работы с АЦП в документации к Вашей плате MAX 10 FPGA Evaluation Kit?

      Результат преобразования АЦП побитно сложен XOR-ом и выведен на светодиод — эта хитрость, которую я обычно делаю чтобы логический компилятор видел, что АЦП используется и не пытался выкинуть модуль АЦП при оптимизации.

      пс: этот сайт — это просто личный блог для удовлетворения периодическои потребности в графоманстве))

      • Текст программы я поначалу не анализировал, т.к. не знаю языка, но все-таки решил посмотреть. Кажется, понял Вашу идею со светодиодом и решил проверить осциллографом. Да, так точно! – там переменный высокочастотный сигнал. Ширина отдельных импульсов 1 мкс. АЦП работает!
        Вопрос теперь в том, как стыковать мою AHDL-программу (1800 строк) с Verilog. Буду думать дальше…
        Спасибо!

      • Нашел ошибку автора статьи, который дал ссылку на Вашу статью.
        Благодаря Вам АЦП заработал, и я сумел понять, почему не работает АЦП в схеме другого автора:
        https://marsohod.org/projects/proekty-dlya-platy-marsokhod3/310-max10-adc
        Описание ошибки я дал в комментарии. Если Вам интересно, и чтобы не копаться в комментариях, привожу текст комментария здесь:

        #4 Alexander Julegin 21.07.2016 09:05
        В статье ошибка автора:
        “На модуль подаю 1МГц с PLL, в параметрах модуля стоит делитель 1.”
        Среди разрешенных частот АЦП нет 1МГц, есть 2,10,20,40,80МГ ц. На рисунке настроек ядра АЦП видно, что используется 2МГц. Поэтому с PLL надо подавать 2МГц, а не 1МГц. К сожалению эта ошибка еще подтверждена рисунком, где видно, что с PLL подается 1МГц, а должно быть 2МГц. Это серьезная ошибка, подтвержденная в 2-х местах. АЦП не работает, а понять ничего нельзя.
        В конце статьи есть ссылка. Я пошел по ссылке на сайт другого блогера и он помог мне разобраться. После исправления ошибки предложенная автором схема заработала.

      • В предыдущем комментарии (см. выше) я дал ссылку на автора, проект которого альтернативен Вашему проекту – тоже нет Qsys и шины Avalon-MM. Занятые ресурсы м/с меньше 1%, возможно это Вас заинтересует. Модуль оформлен в графическом виде с достаточным (но не избыточным) количеством входов/выходов.
        Кстати, меня восхитил предложенный Вами инструмент SignalTap II Logic Analyser. Большое спасибо! Я пока не начал изучать его, но уже на первом примере вижу могучие достоинства. Раньше я отлаживал довольно большую программу на AHDL, не имея этого инструмента. И помню, насколько сложно мне приходилось делать отладку арифметики и логики с большими числами, пользуясь только осциллографом и множеством контрольных точек на плате. Приходилось делать специальные ловушки ошибок и т.п. Анализатор резко упрощает задачу. Буду осваивать…

  2. Большое спасибо, akpc806a!
    Я попробую. Кстати, забыл сказать, что я пробую на плате Альтера-Эвал-Кит:
    Altera_10M08S_E144_eval_schematic_REV_1_0.pdf
    Правда, сегодня не успеваю, а завтра обязательно отпишусь!

  3. I am reading your page via Google Translate (sorry, I cannot comment in Russian). Good job! I have not been able to find the timing diagram you show. Which datasheet is it in? In particular I am looking for values for the times shown in the figure: T(SU,CHSEL) T(H,CHSEL), T(SU,DATA), T(EOC), T(DAC), and T(H,DATA).

    Вот перевод (Google)

    Я читаю вашу страницу с помощью Google Translate (извините, я не могу комментировать на русском языке). Отличная работа! Я не смог найти временную диаграмму вы показываете. Какой техническое описание он в? В частности, я ищу значений времени, показанных на рисунке: T(SU,CHSEL) T(H,CHSEL), T(SU,DATA), T(EOC), T(DAC) и Т(Н,DATA).

    благодаря

Leave a reply to akpc806a Cancel reply