Автор: https://github.com/iwaniwaniwan012
Введение
В протоколах передачи данных для стабильной работы используются кодеки, выбранные разработчиками с учётом следующих требований:
равномерное распределение 0 и 1 в канале
простота кодирования/декодирования
иметь небольшую избыточность
Один из самых распространённых протоколов, о которых думаю, если не каждый человек, то уж каждый инженер точно слышал, является Ethernet, который имеет большое количество стандартов. Он так же использует кодек, а именно 66b/64b, который широко известен в инженерных кругах. Вот небольшой список популярных протоколов, использующих этот кодек:
Ethernet (10,40,100G)
Common Public Radio Interface
Fibre Channel (10G, 16G)
Infiniband (FDR, EDR)
Thunderbolt
Общее описание кодека 66b/64b
Схема кодирования состоит в том, что перед 64 битами данных добавляются 2 бита по следующей схеме:
если 64 бита составляют только данных "полезной нагрузки", то значение 2 бит - b'01
если в 64 битах содержатся данные и служебная информация или только служебная информация, то значение 2 бит - b'10 и значение 1-го байта содержит информацию о том, какого типа служебная информация содержится и её количество
Значения b'00 и b'11 для этих двух служебных бит не используются и будут восприняты как ошибка на приёмной стороне.
Дальше, для равномерного распределения 0 и 1 в канале, полученные данные скремблируются в соответствии с полиномом и передаются в канал связи.
Схема декодирования имеет обратный порядок действий, за исключением того, что в самом начале необходим синхронизатор, так как в канале связи приёмник не обязательно после обработки передаёт нам данные, выровненные на 2 служебных бита в начале.
Модули, необходимые для реализации
Приёмник:
Синхронизатор
Декодер
Дескремблер
Передатчик:
Кодер
Скремблер
Для проверки модулей так же нам необходим TestBench для проверки правильности разработанных модулей.
Небольшое отступление:
Те, кто имеет опыт работы с высокоскоростными интерфейсами ПЛИС фирм Xilinx или Altera/Intel могут сказать, что это всё можно включить в IP ядрах и будут конечно правы, но иногда бывают случаи, когда таких возможностей нет и тогда разработанные модули будут как раз кстати, особенно ввиду текущей обстановки...
Так же, ввиду особенностей IP ядер, реализующих только Physical Media Access, которые могут работать с шинами максимально 64 бита, было решено дополнительно реализовать модули конвертера 64 бита в 66 бит и наоборот.
Итоговая схема работы всего нашего проекта получается следующая:
Алгоритм работы модулей
Конвертеры
Представляют из себя сдвиговый регистр, который в зависимости от текущего наполнения, выдаёт сдвинутые данных.
Проще говоря сдвиговый регистр и мультиплексор.
Синхронизатор
Алгоритм синхронизации состоит в следующем:
Поиск синхронизации осуществляется за счёт объединения двух шин, представляющих из себя данные, полученные на предыдущем такте и на текущем такте.
Если 2 первых бита принимает значение только 2'b10 или 2'b01 в течении 128 тактов, то синхронизация достигнута, если нет, и эти два бита принимают зарезервированные значения, то по истечении 128 тактов сдвиг поиска синхронизации сдвигается на 1 бит.
Если в состоянии синхронизации за 1024 такта получилось 64 ошибки, то синхронизация сбрасывается и происходит переход на поиск синхронизации.
Описание входных/выходных пинов модуля:
port (
Clk : in std_logic; --Тактовый сигнал
Reset : in std_logic; --Сброс
En_In : in std_logic; --входной разрешающий сигнал
Data_In : in std_logic_vector(65 downto 0); --входные данные
Syn_Out : out std_logic; --статус синхронизации
En_Out : out std_logic; --выходной разрешающий выходной сигнал
Data_H_Out : out std_logic_vector(1 downto 0); --два служебных бита
Data_Out : out std_logic_vector(63 downto 0) --данные
);
Скремблер/Дескремблер
Представляет из себя сдвиговый регистр с шиной 58 бит, младший бит которого является очередным битом входных данных. А выходными данными скремблирования/дескремблирования - результат XOR 58 и 39 бита сдвигового регистра, а так же каждого входного бита данных, от младшего к старшему.
Описание алгоритма на VHDL представлен ниже:
if En_In = '1' then
for i in 0 to 63 loop
XorBit := Data_In(i) xor ScrReg(38) xor ScrReg(57);
ScrReg := ScrReg(56 downto 0) & Data_In(i);
DataReg(i) := XorBit;
end loop;
En_Out <= '1';
Data_H_Out <= Data_H_In;
Data_Out <= DataReg;
else
En_Out <= '0';
end if;
Проверка в среде симуляции
TestBench для среды симуляции по сути является генератором данных (последовательный счётчик), а на приёмной стороне проверка, что текущие данные это значение предыдущих данных -1. Так же на приёмной стороне, для визуальной проверки, если предыдущее условие выполняется, то сигнал Data_Test_Ok принимает значение 1'b1, в противном случае 1'b0.
Требуемые ресурсы ПЛИС и максимальная частота
При разработке различных модулей ПЛИС, перед использованием их в реальном проекте, мы используем тестовый проект с внутренним названием TestFreq, где используем входные пины модулей как виртуальные пины, тем самым проверяем, какое количество ресурсов ПЛИС будет использовано, а так же на какой максимальной частоте он сможет работать, причём в большинстве случаев второе является более важным.
Такие же измерения мы решили провести и для наших разработанных модулей (ПЛИС Intel/Altera). Результаты представлены в таблице ниже:
ПЛИС |
Ресурсы |
Максимальная частота |
Cyclone IV |
1906 LC |
179 MHz |
Cyclone V |
885 ALM |
188 MHz |
Stratix IV |
947 ALM |
333 MHz |
Stratix V |
901 ALM |
471 MHz |
Итог
По результату у нас получилось реализовать кодек 66b/64b, который можно использовать для различных проектов, где нет готовых решений или по какой-то причине мы не можем их использовать.
Ссылка на исходные коды, включая ТеstBench и описание, - кодек 66b/64b на языке VHDL
Спасибо за внимание!
P.S. Комментарии и пожелания крайне приветствуются =)
Комментарии (4)
m1kr1k
07.12.2023 06:18У вас на схеме исходные 66 бит сжимаются до 64, а затем в декодере опять ппреобразуются в 66. Наверное, всё-таки, должно быть наоборот.
pcbteach Автор
07.12.2023 06:18На схеме всё указано верно.
Возможно вы неверно поняли, идея конвертера не сжать данные, а из шины 66 бит перейти в шину 64 бита, так как, учитывая опыт использования высокоскоростных приёмопередатчиков, шина 66 бит обычно не доступна для выбора. Варианты зачастую такие 32,40,64 бит на такт. А при формировании и обработке данных с использованием кодека 66/64 удобно, когда за один такт сразу приходят данные 64 бита, и "служебка" 2 бита.
aystarik
А вот этот проект не смотрели? https://zipcpu.com/blog/2023/11/25/eth10g.html
pcbteach Автор
На момент написания статьи этот проект не встретился, а на момент разработки кодеков его ещё не было. Модули были разработаны задолго до того, как появилась эта статья. Тогда мы и решили их выложить в github, так как не нашли готовых, хотя разработка их не была чем-то сложным. А теперь решили написать статью по этому поводу. Так что если кто воспользуется нашими наработками будет отлично =)