Блог им. karat39

Как я логи на RGMII подымал и выводил их в ModelSim

Введение

     Так получилось, стал я обладателем борды, на которой есть все, кроме JTAG. Это означало, что такого софта как SignalTAP у меня нет. Отлаживать не получится. Подымать карту в слепую то еще занятие. Это как копаться в черном ящике в темной комнате. Было принято решение, начать писать логи на карте и передавать их в каком нибудь формате через Ethernet на компьютер. На основе этого был получен некоторый опыт, описать который захотелось. Сильно особо не критикуйте, эту тему я изучаю полностью с нуля, давалось и дается fpga (как и схемотехника) очень тяжело, когда нет специализированного образования.

ETHERNET

     Вообще ethernet — это технология передачи данных. Жестко стандартизирована по IEEE. Подстандартов сейчас очень много, технологии не стоят на месте. Наверное слышали 10Base-T (10Мбит/сек), 100Base-T, 1000Base-T(1Гигабит/сек), ну или как на нашей бирже 10GBase… Самая сложность реализации на железе этих стандартов — это реализация физического уровня, то есть как передаваемые вами байты в сеть преобразовывать в электрические сигналы, используя кодировку и тд. Если поднять с нуля 10Base-T не представляется сложным, делал это без проблем даже без специальных magnetic на разъеме RJ45, то скорости повыше это задачка уже так себе. Ну еще можно без каких либо сильных сложностей поднять 100Мбит. 
    Поэтому разработчиками всякого железа было в свое время придумано засунуть реализацию физического уровня Ethernet в какую нибудь дешевую микруху, которая на себя возьмет полностью реализацию всего. Наверняка вы слышали таких производителей, как Realtek, Marvell и др. Использование таких микрух достаточно оправдано, за небольшие деньги вынести в отдельный модуль решение массы задач. Это гораздо упрощает решение задачи + нет нагрузки на саму fpga, освобождаются ресурсы под другие задачи.
    Мне повезло. На моей борде стоит такой чип от Marvell. 

RGMII

     Так как я уже ранее сказал, что любая эта тема является жестко стандартизированной, то и работа с такими чипами тоже описана стандартами, а если быть корректней, то протоколами. Для передачи данных на физический уровень Ethernet были разработаны различные протоколы. Ну например: MII, SGMII, RGMII и тд. Их описание вы легко прочитаете в инете. Ну и тут мне повезло, мой Marvell поддерживает RGMII. Это значит, что я могу работать с ним на fpga на пониженных частотах (125Mhz), это повысит надежность кода, алгоритма и повысит стабильность выполнения задачи.
     Я решил максимум отладить код в ModelSim, а потом пробовать его в слепую запускать на fpga. Кстати говоря, раньше давно я не дооценивал ModelSim, любил SignalTAp и отлаживать сразу на бою в рабочем состоянии. Как потом показал опыт, качественно отлаженный код в ModelSim запускается с первого раза на карте. В том числе и 1000Base-T я запустил на карте с первого раза, после недельной отладки в ModelSim. Это очень сильно экономит время, так как компилирование и прошивка fpga — это вам не c++ закомпилить. Это минут 15-20.
     Все что вам нужно знать для отправки сетевого пакета на физический уровень сети через протокол RGMII, так это шесть сигналов: tx_clk, tx_ctrl, tx_0, tx_1, tx_2, tx_3. Качественно их подготовив и подав на микруху Marvell (ну или Realtek), вы получите результат => отправка битов в витую пару. Их описание:
      — tx_clk. Это сигнал генератора на частоте 125Mhz. Грубо говоря, если мы переведем герцы в наносекунды, то получим, что каждые 8наносек (125Mhz = 8наносек), мы просто должны подавать электрический сигнал (логическую 1) на ножку чипа Marvell
      — tx_ctrl. Это сигнал управления передачи. Если на эту ножку подаем логическую 1, то мы говорим микрухе, что мы передаем в сеть биты. И она начинает работу и передавать биты. Если мы на эту ножку ничего не подаем (логический 0), то микруха молчит.
     - tx_0, tx_1, tx_2, tx_3. — Это как раз значения передаваемых битов. Соответственно, если на какую то ножку мы подаем электрический сигнал, то значения соответствующего бита = 1.
    Легко понять, что у нас всего 4 ножки под значения битов. То есть передаем 4 бита, а байты в компьютере состоят из 8 битов. Вот тут и вступают правила RGMII. В любом описании в инете вы найдете нечто похожий текст, что по переднему фронту сигнала tx_clk мы передаем первые 4 бита, по заднему фронту вторые 4 бита. Неподготовленному бойцу может стать и не понятно. Попробую нарисовать это:
Как я логи на RGMII подымал и выводил их в ModelSim


Если нарисовать алгоритм RGMII блок схемой:
Как я логи на RGMII подымал и выводил их в ModelSim

     Все в принципе просто. Особенно когда переваришь тонну материалов в интернете. Но есть нюансы. Может получиться такая ситуация, и практически 100% вероятность, что она получится, когда вы подаете на ногу тактовый сигнал tx_clk, а сами ноги бит tx0..tx3 чуточку запаздывают, на считанные наносекунды. Это может вызвано несколькими причинами. Самим FPGA и вашим кодом, либо схемой платы, ее пайкой и тд. То есть передача сигналов по самой плате передаются с задержкой. Обычно производители плат в документации составляют целую таблицу задержек тех или иных сигналов по плате (особенно актуально, когда вы подымаете sfp+ или pci-express на карте). В связи с этим, принято сдвигать тактовый сигнал на величину задержки, а еще актуальней просто сдвигать его на 90 градусов, если схематично, то сдвинуть его вправо, пометил его зеленым на рисунке
Как я логи на RGMII подымал и выводил их в ModelSim
Тогда гарантированно при подаче тактового сигнала tx_clk, микруха Marvell считает именно нужные биты со своих ног tx0..tx3 и tx_ctrl.

Ethernet кадры и UDP

     Вообще не уверен что это тема этого топика. Поэтому совсем немного. Сеть Ethernet так устроена, что данные передаются кадрами, cформированными по определенным правилам. Вы не можете заслать в кабель через микруху любую последовательность байт и ожидать результата. Для начала нужно собрать ethrnet кадр по спец правилам и начать его передавать в кабель.

1) Для начала в кабель нужно заслать преамбулу кадра. Это просто 7 байт с шестнадцатеричным значением 55 (1010101 в двоичном).
2) Далее нужно заслать 1 байт разделителя после преамублы. Его значение D5 в Hex.
3) Далее нужно заслать в  кабель 6 байт MAC адреса получателя
4) Далее нужно заслать в  кабель 6 байт MAC адреса отправителя. Будьте тут внимательны, вбивайте правильно значение, чтобы не намаяться с отладкой.
5) Если у вас сеть, как на Мос бирже колокейшен, то нужно заслать заголовок VLAN
6) Далее идут данные кадра (TCP или UDP пакет)
7) И все это дело заканчивается контрольной суммой кадра. Это 4 байта. Правильно высчитанное значение контрольной суммы очень важно. Если сумма не корректна, если у вас ошибка кода, то ваш кадр просто не дойдет до получателя. Намучаетесь много.

     Лично мне помогали вот эти две ссылки. Я в ModelSim выводил значения засылаемых в кабель данных и проверял тут правильность сгенерированных кадров в hex.
packetor.com/
www.gasmi.net/hpd/
    Честно говоря, мне лень описывать этот раздел. Я уже к этой строке потратил полтора часа подготовки текста и лень меня одолевает. Если вам интересно будет, задайте просто вопрос, я расскажу.

Контрольная сумма

     Код или модуль контрольной суммы нужно написать так, чтобы она пересчитывалась online, по мере поступления очередного байта в кабель. Ведь у нас FPGA и мы должны использовать все преимущества параллельных расчетов. Поэтому код нужно составить так, чтобы к моменту посылки контрольной суммы в кабель, она уже была рассчитана иначе ее расчет потянет за собой задержки и вы просто можете не уложиться в заданный такт tx_clk. Если будет интересен ее код или ее алгоритм, задайте вопрос, я тоже покажу.

Организация логов

     Тут все очень просто. Задача очевидная. Нам нужно сохранять значения каких то сигналов или значения переменных или значения регистров с заданной частотой. А отправлять эти значения с конкретной частотой 125Mhz (скорость, на которой работает RGMII Marvell). В моих потребностях логи я пишу с частотой 100Mhz (1 раз в 10 наносекунд). Очевидно, что эту задачу может решить асинхронный буфер FIFO. В Quartus есть такая мегафункция. Ее просто нужно подключить и настроить.
    Формат логов у меня пока очень простой. Первые 2 байта я использую под порядковый номер лога + еще 1 байт под значения восьми сигналов (1 байт = 8 бит). Получается, в асинхронный FIFO я сохраняю каждые 10наносек 24 бита (3 байта по 8 бит). И вытаскиваю из этого буфера эти 24 бита каждые 8 наносек и отправляю в сеть.
    Очень упрощенно это выглядит так:
Как я логи на RGMII подымал и выводил их в ModelSim

Принимающая сторона

     Тут надо признать, я немного намучался. Скорость логов была такова, что даже зависала сеть, не говоря уже о подвисании компьютера. Слегка решил проблему, когда увеличил размер посылаемого лога в притирку к MTU = 1500 байт. Этим самым мне удалось добиться разрыва между пакетами чуть больше 1мксек. До этого решения, у меня посылалось примерно до 3 пакетов в 1 мксек и у меня жутко висела вся сеть. Даже если свитч выдерживал нагрузку, то компьютер не справлялся.
     Когда я поборол зависания путем уменьшение частоты пакетов, я столкнулся с проблемой визуализации как в SignalTAP. Все решения рисования графиков на c#, на .Net, Excel тупиковые. Они просто не справляются таким потоком данных и самое главное таким кол-ом набора данных. Но плавно пришло решение. Я просто погружал эти данные в ModelSim с помощью написанного мною TestBench.
    В итоге связка получилась такая. Я на c# написал сниффер сети. Сырые сокеты не стал использовать, взял готовое решение для .NET PCAP (на нем работает и Wireshark). Сниффлю я все пакеты с MAC отправителя моей FPGA (там я просто прописал 000102030405), PAYLOAD (полезные) данные из UDP пакета я просто побайтно сохраняю в файл. И потом этот файл просто загружаю в ModelSim с помощью TestBench.
Выглядит это вот так:
Как я логи на RGMII подымал и выводил их в ModelSim

    По моему получилось супер. Тема логов очень актуальна. Гигабитный RJ45 очень выручает в этом плане. Мы не засоряем боевые каналы передачи данных (SFP+ 10G, PCI-E) где ходят торговые данные. + Визуализация отладки мне понравилась. Тормозов нет, все в виде осцилограммы. И самое главное в таком решении, нет ограничения по времени логов, как это в SignalTAP, где время собираемых логов ограниченно свободной памятью fpga. Получился некий скоростной логический анализатор. Буду рад услышать критику или ваши похожие решения.

ps. Кода в посте совсем не было. Ну пусть будет хоть кусок TestBench на Verilog =))
ps2. В поддержку Тимофея и его Смартлаб.
ps3. В настройках подсветки кода нет настройки Verilog (видно разработчики не ожидают тут фпгаашников), так что будем довольствоваться подсветкой c++
`timescale 1ns / 1ns
module main_test_bench_125_1; 
	/*
	Формат лога в сетевом пакете:
	
	struct {
			uint16_t	log_id;					Два байта порядкого номера лога
			uint8_t		signal_values;			8 бит со значениями восьми сигналов
	}
	
	*/
	
	//Сигналы для вывода на осцилограмму
	reg     	clk_100Mhz; 					//Осцилограмма генератора 100Mhz
	reg [15:0]	log_row_id;						//Первые 2 байта лога - порядковый номер
	reg			signal_1;						//Первый бит третьего байта лога - значение первого сигнала в логе
	reg			signal_2;						//Второй бит третьего байта лога - значение второго сигнала в логе
	reg			signal_3;
	reg			signal_4;
	reg			signal_5;						//...
	reg			signal_6;
	reg			signal_7;
	reg			signal_8;						//Восьмой бит третьего байта лога - значение восьмого сигнала в логе
	
	//Вспомогательные переменные
	integer 	file_log;						//Указатель на файл с логами
	integer		scan_file;

	initial
	begin
		//Пытаемся открыть файл с логами
		file_log = $fopen("udp_dump.bin", "r");
		if (file_log == 0) 
		begin
			$display("Log file open FAILED");
			$finish;
		end
		
		//Имитируем тактовый генератор 100Mhz
		clk_100Mhz  = 1'b0;			//Начальное значение 0
		#5;							//Задержка сигнала 5нс (100Mhz = такт 10нс, 5нс - полу такт)
		repeat(24999999)
		begin
			clk_100Mhz  = 1'b1;		//Ставим генератор в 1
			#5  clk_100Mhz  = 1'b0;	//Ждем 5нс и ставим генератор в 0, фактически имитируем сигнал 1 в течении 5нс
			#5;						//Ждем 5нс и ставим генератор в 1, фактически имитируем сигнал 0 в течении 5нс, получаем 1 такт длительностью 10нс
		end
		clk_100Mhz  = 1'b1;
		#5;
	end

	//На каждый такт генератора читаем данные из файла и выводим их в сигналы осцилограммы
	reg [7:0]	byte_1;
	reg [7:0]	byte_2;
	reg [7:0]	byte_3;	
	
	always @(posedge clk_100Mhz) 
	begin
		byte_1 = 0;
		byte_2 = 0;
		byte_3 = 0;
		
		scan_file = $fscanf(file_log, "%c%c%c", byte_1, byte_2, byte_3);	//Читаем 3 байта в 3 регистра по 8 бит
		if (!$feof(file_log)) 
		begin
			log_row_id [15:8] 	= byte_1;									//Назначаем прочитанные значения на выводы осцилограммы
			log_row_id [7:0]  	= byte_2;
			signal_1			= byte_3 [7];
			signal_2			= byte_3 [6];
			signal_3			= byte_3 [5];
			signal_4			= byte_3 [4];
			signal_5			= byte_3 [3];
			signal_6			= byte_3 [2];
			signal_7			= byte_3 [1];
			signal_8			= byte_3 [0];
		end
	end	
	
	initial
	#1000000000 $stop;			//После 1млрд наносекунд (=1 сек), заканчиваем моделирование
endmodule




  • Ключевые слова:
  • fpga
★10
36 комментариев
Сколько же времени убили на написание кода для отладки ?
Не дешевле ли было раскошелиться на новую карточку ?
Или умельца привлечь, JTAG подпаять? Физически то он на всех Altera есть, просто на карточке может быть не подключен.
Проц не задействовали для передачи, чисто на конечных автоматах?
avatar
Jame Bonds, 
Или умельца привлечь, JTAG подпаять?
Я месяц подымал плату. Она не пускалась. Достал всех. В том числе и саму альтеру. Запустил.

До JTAG не дошли руки (дошли, но не получилось). Просто устал. Есть мнение, что он закорочен до меня. Конкретно первая нога (tck). Прочитал глупый совет на форуме альтеры, начать подавать повышенное питалово от альтернативного источника (начал подавать 3.3 вольта) на эту ногу, закаротка начала по тихоньку пропадать, начало расти сопротивление. Но ничтожно медленно. А 5 вольт, как написано было в совете, я боюсь подавать, спалю альтеру, жалко будет.
avatar
Андрей К, что ж за плата такая, с которой столько мучаетесь. Подпаленная БУ что ли ?
Новые платы можно взять начиная с 1,5k$, зависит от класса. Просто нерационально убивать месяц работы на починку.
avatar
Jame Bonds, бу, не ожидал что подпаленная =). За полторы не нашел новые, чтобы были трансиверы, да сразу побольше =)
А начинал в свое время с циклона 4 SX, но на нем далеко не уедешь.
avatar
Андрей К, SFP? Есть вот такой мезонин + базовая плата (выбор большой). Проблема только в том, это вместе при подключении в PCIe не лезет в стандартный корпус. Решается шлейфом-удлинителем для PCIe.
А если Gb Ethernet, то еще дешевле и вариантов море.
avatar
А времянка подстраивается элементарно, без всяких переворотов клоков следующим образом:
1) Находите в характеристиках микросхемы приемника (ваш PHY) параметры tsu, th;
2) Рассчитываете по ним tco, tcomin;
3) Прибавляет к ним разницу задержки в дорожках (для 125 МГц она ничтожна, можно игнорировать);
4) Задаете параметры в Quartus;
5) Quartus сам подбирает задержки во время Fitter и проверяет, что попал в Timing Analizer.
Так гораздо быстрее, чем подбирать руками. Кроме того гораздо надежнее, так как задержки все равно немного плавают от температуры и кристалла (в смысле на другой ПЛИС того же типа), и нередко «подобранные руками золотые задержки» перестают работать совершенно неожиданно.
При применении расчета даже если при разводке по кристаллу параметры сломаются, увидите предупреждение в отчете.
avatar
Jame Bonds, 
А времянка подстраивается элементарно, без всяких переворотов клоков следующим образом:
Спасибо за подробный совет. Я его сохраню. Timing Analizer я действительно юзал. Но не смог добиться устойчивости.

Когда подымал 10Base действительно перебрал методом тыка частоту.
avatar
Jame Bonds, 
1) Находите в характеристиках микросхемы приемника (ваш PHY) параметры tsu, th;
2) Рассчитываете по ним tco, tcomin;
Вот на именно мой Marvell, он редкий, я мануал не нашел. Перерыл форумы. Есть на похожий мануал, но не мой. А Marvell в свободный доступ полный даташит не дает.
avatar
Андрей К, ну да, известная проблема. Если модель скажете, могу посмотреть в астралах.
avatar
Jame Bonds, в любом случае, спасибо за помощь
Marvel's 88E1118R
avatar
Андрей К, увы, нашел только 1111 и 1112
avatar
Jame Bonds, все равно спасибо =). У меня вообще документаций нет к моей борде. Подымал все методом тыка. Пины прозванивал мультиметром и тестовым кодом через диоды =)) Уже привык.

Знал бы, что существует услуга рентген плат, воспользовался незамедлительно
avatar
Андрей К, а как же ножки назначали? На www.altera.com доки по всем официальным отладочным платам. Или у вас раритет типа Bittware или Таганрожский НИИ МВС ?
А рентген мало поможет, во-первых скорее всего он внутри микросхемы, а не между проводниками, а во-вторых на многослойке рентгеном можно увидеть только закоротку припоем под корпусом.
avatar
Jame Bonds, борда сама не альтеровская. Не раритет, но и не самая свежая, года так 2013.

Какие то ножки, особенно jtag, трансиверы и marvell звонил обычным мультиметром.  Купил самые острые наконечники, заострил их наждаком еще больше и тыкал по плате. Альтера то BGA, с обратной стороны доступ есть. 

Все остальное не получилось вызвонить (диоды, генераторы и тд). Перекрестился, подал на все 650 штук пользовательские пины 0, диоды загорелись. Ну а дальше дело техники. Сужал диапазон ножек в прошивке и вычислял конкретные ноги.

Генераторы тоже дело техники. Начал брать каждую ножку с функцией клока из Pin Planner, сделал через нее делитель частоты и выводил на диод. Грубо говоря заставлял моргать диод. Примерно после 19 прошивки я вычислил оба генератора. Секундомером замерил кол-во морганий и вычислил частоту, что подтвердило приблизительно маркировкой (как смог разглядеть через двойную лупу)

Ну вот как то так. Гораздо интересней вспоминать как я плату подымал и как мне помогали американцы =)). Я даже статейку на СЛ написал, но удалил, не понравилось. Сумбурный поток мыслей
avatar
Я конечно все понимаю, но зачем эту техническую ересь публиковать на смарт-лабе? Думаете пользователи массово бросятся подавать 5 вольт на микросхемы?
avatar
Elstoun, ну например с Jame Bonds фразами перекинуться.
avatar
 Андрей К, ну, было бы здорово немного остальным рассказать для чего все это делается. Интересно, но гуглить лень. Это как-то связано с ускорением прямого доступа к бирже, минуя терминал и брокера?
avatar
tranquility, да, мои топики все на эту тему
avatar
Совсем школьники расслабились… логи по эзернету им… С магнитной ленты данные считывать, когда у тебя пара инструкций процессора сжирают уже и передний и задний фронт  — вот где реальная работа с таймингами :)
avatar
bstone, да ладно, какие школьники. Раз вы застали такие задачи, я тогда на уровне яслей =)
avatar
Андрей К, так я это сам в яслях делал, так что молод пока ещё душой :)
avatar
Крайне редко сюда захожу, приятно было на главной увидеть твой пост) Если что у меня все хорошо)
avatar
Александр, привет, рад за тебя =)
avatar
Теперь с нетерпением жду кулинарных рецептов на Смартлабе… )
avatar
Это больше по Хабровской теме статься, к трейдингу то какое отношение ? 
avatar
Skifan, скорее всего самое прямое =)
Кстати, Тимофей примерно с год назад жаловался вслух, почему хабровцы не пишут у него.
avatar
Skifan, отношение к трейдингу прямое.
старый трейдер, 
для быстрой проверки подобных подозрений существует древнейший прием: подносим кусок феррита к дорожкам и наблюдаем эффект. Малые запасы по фазе проявятся сразу. 
сейчас платы многослойные, на поверхности то и дорожек нет, все внутри. Наверняка поможет рентген платы. Это даже не дорого стоит, но у меня просто руки не дошли.
 И, наконец, если это для торговли, то не тупиковый ли путь?
почему нет?
avatar
Андрей К, даже всевозможные учебники по бизнесу как мантру воспроизводят фразу о необходимости уникального преимущества. Соответственно, если скорость — основное преимущество..., см. историю HFT.

Судя по происхождению платы, речь идет не о работе на заказчика. Если это так, советую посмотреть в противоположную сторону. На рынке полно «вечных неэффективностей», порождаемых человеческой психикой.

Если подача 3.3В прошла успешно, то вероятность настоящего к.з. мала. Для начала можно подцепить осциллоскоп и посмотреть.

старый трейдер, 
Судя по происхождению платы, речь идет не о работе на заказчика.
я сначала учился на тестовых китах с алиекспресса. В целях самообразования. Потом когда на нем было максимум опробовано, кое что реализовано и пройдены основные начальные этапы разработки, было принято решение брать что то помощней.
Так как я не нашел новых плат за 1500$уе, а найденные за 6500$+ было жалко портить неправильными действиями, решено было брать то что есть сейчас =).
На ней получен уникальный опыт, что в принципе наверное можно уже и спалить новую и потом ее восстановить =).
Если подача 3.3В прошла успешно, то вероятность настоящего к.з. мала
начитался на форумах, что если подать на банк fpga вольтаж больше его наминала, то можно пальнуть весь банк. Там где сидит JTAG, номинал банка как раз 3.3. Я поэтому больше не рисковал. Но думаю, когда эта карта станет запасной, я все таки попробую. Кстати спасибо за совет про 20мА, я бы туда точно амперов бы 5 подал, у меня такой универсальный БП для карты (robiton).
Если это так, советую посмотреть в противоположную сторону
конечно. Мои личные бюджеты, возможности не осилят того, чем занимаюсь.
avatar
Андрей К, понятно, тогда добавлю лишь, что 20мА нужно подавать через резистор в сотни Ом, чтобы емкости БП не вредили.

Потрясающая статья
avatar
Anton, спасибо, ещё готовлю
avatar

теги блога Андрей К

....все тэги



UPDONW
Новый дизайн