Есть простой способ симуляции АЦП, встроенной в ПЛИС Intel MAX10. Если сказать точнее, то существует простой способ симулировать выходные данные АЦП в среде ModelSim.
Сейчас расскажу, как это сделать.
Когда в проекте для FPGA MAX10 нужен компонент АЦП, то он создается через пункты меню Tools => IP Catalog, далее в списке выбираем Library => Processors and Periferials => Altera Modular ADC core. Далее открывается IP Parameter Editor, где задаются конкретные параметры и нужная конфигурация модуля АЦП. Довольно подробно про это рассказано в описании проекта Использование встроенного в Altera MAX10 АЦП.
Как показано на рисунке выше, на этапе редактирования IP параметров для АЦП можно указать путь к текстовому файлу, который будет содержать отсчеты АЦП, которые увидит потом ModelSim во время симуляции.
Чтобы проиллюстрировать эту возможность я написал простую программу на C/C++, которая имитирует отсчеты аналогового сигнала и печатает их в консоль:
#include "stdafx.h"
#include <iostream>
#define _USE_MATH_DEFINES 1
#include <math.h>
int main()
{
int i = 0;
double t;
double w = 2 * M_PI * 50;
for ( t = 0.0; t < 20.0; t += 1.0/50000 )
{
double val = sin(w*t);
w += 0.5;
std::cout << i << " " << (val + 1.0)/2.0*3.2 << "\n";
i++;
}
return 0;
}
Программа имитирует аналоговый сигнал от 0 до 3,2 вольта, начинаются низкочастотные колебания 50Гц, затем в течении 20 секунд частота колебаний постепенно растет.
Если скомпилировать и запустить такую программы и ее вывод перенаправить в файл, то получим простой текстовый файл вот с такими отсчетами:
0 1.6
1 1.61007
2 1.62017
3 1.6303
4 1.64046
5 1.65066
6 1.66088
7 1.67113
8 1.68141
9 1.69172
10 1.70206
11 1.71243
12 1.72282
13 1.73324
14 1.74369
15 1.75416
16 1.76465
17 1.77517
18 1.78572
19 1.79629
20 1.80688
...........
Здесь две колонки: номер отсчета и значение аналогового сигнала в вольтах, число с плавающей точкой. На этот файл будет ссылаться наш модуль АЦП во время симуляции.
Простейший проект, который использует АЦП ПЛИС на плате Марсоход3, может выглядеть вот так (Verilog HDL):
module top(
input wire CLK100MHZ,
output reg [7:0]LED
);
wire clk2MHz;
wire clk_locked;
mypll mypll_inst (
.inclk0( CLK100MHZ ),
.c0( clk2MHz ),
.locked( clk_locked ) );
wire [11:0]adc_data;
wire adc_data_clk;
fiftyfivenm_adcblock_top_wrapper #(
.device_partname_fivechar_prefix ("10M50"),
.clkdiv (4),
.tsclkdiv (0),
.tsclksel (1),
.refsel (0),
.prescalar (0),
.is_this_first_or_second_adc (1),
.analog_input_pin_mask (65536),
.hard_pwd (0),
.enable_usr_sim (1),
.reference_voltage_sim (65536),
.simfilename_ch0 ("C:/altera/MAX10/max10_adc_sim/sin/Debug/wave.txt")
) adc_inst (
.chsel ( 5'd0 ), // 5-bits channel selection.
.soc ( 1'b1 ), // signal Start-of-Conversion to ADC
.eoc ( ), // signal end of conversion.
//Data can be latched on the positive edge of clkout_adccore after this signal becomes high.
//EOC becomes low at every positive edge of the clkout_adccore signal.
.dout ( adc_data ), // 12-bits DOUT valid after EOC rise, still valid at falling edge, but not before the next EOC rising edge
.usr_pwd ( 1'b0 ), // User Power Down during run time. 0 = Power Up; 1 = Power Down.
.tsen ( 1'b0 ), // MUST power down ADC before changing TSEN. 0 = Normal Mode; 1 = Temperature Sensing Mode.
.clkout_adccore ( adc_data_clk ), // Output clock from the clock divider
.clkin_from_pll_c0 ( clk2MHz ) // Clock source from PLL
);
always @(posedge adc_data_clk)
LED <= adc_data[11:4];
endmodule
Идет оцифровка, и полученные выборки сигнала выводятся на светодиоды. Понятно, что в реальности на светодиодах моргание 50Гц врядли увидишь, но мне это сейчас не важно, я просто хочу показать, как это симулируется. Кстати, обратите внимание на параметр simfilename_ch0 модуля adc_inst. Параметр явно указывает на текстовый файл с выборками сигнала. Если используются несколько каналов АЦП, то для каждого канала можно задать свой вайл с отсчетами.
Тестбенч для симулятора, написанный на Verilog:
`timescale 1ns/1ps
module tb;
initial
begin
//$dumpfile("tb.vcd");
//$dumpvars(0, tb);
//#100000000;
//$stop;
end
reg clk = 1'b0;
always
clk = #5 ~clk;
wire [7:0]led;
top top_inst(
.CLK100MHZ( clk ),
.LED( led )
);
endmodule
Здесь в тестбенче просто имитируется тактовая частота 100МГц платы Марсоход3, подаваемая на ПЛИС MAX10, в которую загружен проект, модуль top.
Симуляция в ModelSim ведется как обычно (на нашем сайте есть краткая инструкция), однако, поскольку проект использует IP компоненты альтеры, то в начале симуляции нужно еще добавить ссылки на библиотеки альтеры в диалоге ModelSim:
После этого, можно симулировать, команда run 100000000 несколько раз подряд, запускает симулятор и становится видно наш "аналоговый" сигнал, как последовательность отсчетов в ModelSim:
Описанный здесь метод довольно хорош, но есть у него "небольшая проблемка" - очень медленно идет симуляция. Вообще симуляция всегда идет медленно, когда исходная тактовая частота 100МГц, и исследуются очень медленные процессы на частоте, скажем 200кГц, как в моем случае - 200кГц частота оцифровки сигнала. Кроме того, я пытаюсь посмотреть довольно длительный промежуток времени, хотя бы несколько секунд. Вот такие симуляции всегда происходят медленно, ведь симулируются сотни миллионов событий тактовой частоты...
Тем не менее, как видите, симулировать поток данных из АЦП ПЛИС Intel MAX10 вполне можно.
Подробнее...