ETHERNET 802.3 передача пакета. (Как рассчитать CRC32).

 

     В одном из проектов на основе программируемой логики (FPGA) понадобилось передавать данные

по Ethernet. При этом необходимо было сделать проект как можно проще:

- Без раскручивания полноценного стека протоколов.

- Без применения внешнего микроконтроллера и т.п.

    Для передачи данных был выбран протокол UDP, как наиболее простой в реализации.

Для того чтобы передавать данные необходимо сформировать служебные поля (заголовки) для:

1. 802.3 (Ethernet).

2. IP - протокола.

3. UDP - протокола.

    Заголовки IP и UDP были сгенерированы заранее при помощи ПО EthernetUDP взятую с сайта

проекта fpga4fun.

    Данное ПО позволяет сформировать ETHERNET пакет (с параметрами заданными пользователем)

и вывести в окне программы в виде массива байт.

 

Обновление: На дворе 2021 год, EthernetUDP - перестала запускаться выводя ошибку:

run time error 217.

Пересобрал (при помощи Delphi 7) программу предварительно выкинув все лишнее

по работе с COM портом.

В оригинальной программе создаваемый пакет посылался в COM порт.

Новая версия EthernetUDP_2021.zip

 

   

Формирование пакета ETHERNET не вызывает вопросов за исключение расчета контрольной суммы,

тут не все так просто как может показаться, поэтому рассмотрим процесс подробнее.

 

Расчет контрольной суммы 802.3 ETHERNET.

   

    Функция расчета CRC32 представлена в файле crc32.v

На входе функция принимает 8 бит данных - data_in, на выходе crc_out - 32 разрядная контрольная

сумма crc_out.

 

Алгоритм расчета следующий:


1. Произвести начальную инициализацию crc = 0xFFFFFFFF.

Для этого производится сброс модуля расчета контрольной суммы, путем перевода сигнала rst в 1 и

затем в 0.

(При этом внутряя переменная lfsr_q = FFFFFFFF)

2. Включаем расчет контрольной суммы переведя сигнал crc_en в 1 и подавая входные данные в

переменную data_in.

В конце (после окончания данных) переводим сигнал crc_en в 0.

 

ВНИМАНИЕ:

Данные в data_in необходимо подавать в развернутом(зеркальном) виде, то есть меняем порядок

следования бит:

              ст.7 бит                                                                            мл. 0 бит
.data_in( {data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]} )

3. Полученное значение CRC32 инвертируем (XOR-рим с значением FFFFFFFF).

4. Передаем полученное значение CRC32 в конце кадра ETHERNET.

 

ВНИМАНИЕ:

В Ethernet(802.3) принят следующий порядок передачи данных: МЛАДШИЕ вперед

(от младшего к старшему) !

Передача значения CRC32 осуществляется СТАРШИМИ вперед, т.е. значение необходимо

развернуть (зеркально).

 

Т.е. передача идет в следующем порядке (по номерам индекса):

N бита передаваемых данных 0, 1, 2, 3, 4, 5.....31
N бита crc32 31,30,29,28,27,......0

 

Тестовый проект.


    Для отработки передачи пакета был создан тестовый проект позволяющий непрерывно

передавать UDP пакет в сеть.

    Проект создан на языке Verilog, для отладочной платы DE0-NANO. В качестве ETHERNET трансивера

применен LAN8720 с интерфейсом RMII (плата WaveShare LAN8720 ETH Board).

    В файле ram_ip_paket_tx.mif располагается тестовый пакет с описанием всех заголовков и данных.

Данный файл является образом памяти RAM, из которой осуществляется передача пакета в сеть.

Изменяя значения можно настроить передачу под другие параметры сети и т.п.

 

    После компиляции проект занял 184 LE.

 

    Для диагностики принятых пакетов на ПК применялась программа Wireshark.

 


Модуль передачи пакета V2.0. 

Автоматизация процесса создания пакета.

 

Июнь 2023

По результатам работы с модулем передачи UDP пакета на практике оказалось не очень удобно заполнять поля заголовков в ручную, особенно если проекты разные и часто требуется менять длину пакета, да и ошибок при заполнении никто не отменял.

В результате было принято решение автоматизировать процесс заполнения полей. 

Для удобства формирования заголовков eth, ip, udp пакета была создана утилита generator_udp_packet командной строки позволяющая формировать Ethernet пакет с заданными параметрами.

Утилита generator_udp_packet делает тоже самое что и EthernetUDP но со следующими отличиями:

Работает из командной строки, что позволяет формировать пакет из скрипта, все параметры в командной строке всегда на виду и нет необходимости вспоминать какие были загружены параметры ранее.

Результат работы (ETH пакет) записывается в бинарный файл.

Бинарный файл пакета преобразуется(утилитой bin2mif) в файл инициализации RAM/ROM памяти FPGA, для последующей загрузки в проект.

 

Пример запуска:

generator_udp_packet.exe ffffffffffff 66778899aabb 192.168.12.255 192.168.12.100 10000 10000 255 udp_header.bin

 

Где:

ffffffffffff   - MAC адрес получателя

66778899aabb   - MAC адрес отправителя

192.168.12.255 - IP адрес получателя

192.168.12.100 - IP адрес отправителя

10000          - UDP порт получателя

10000          - UDP порт отправителя

255            - длинна данных UDP пакета

udp_header.bin - имя файла пакета

 

Полученный файл пакета преобразуется утилитой bin2mif в файл инициализации RAM/ROM памяти FPGA.

Пример файла скрипта для Xilinx формат COE:

generator_udp_packet.exe ffffffffffff 66778899aabb 192.168.12.255 192.168.12.100 10000 10000 255 udp_header.bin
bin2mif.exe -coe -datawidth 8 -i udp_header.bin -o udp_header.coe