Автор: 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 в канале, полученные данные скремблируются в соответствии с полиномом G(x) = 1 + x^{39} + x^{58} и передаются в канал связи.

Схема декодирования имеет обратный порядок действий, за исключением того, что в самом начале необходим синхронизатор, так как в канале связи приёмник не обязательно после обработки передаёт нам данные, выровненные на 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)


  1. aystarik
    07.12.2023 06:18

    А вот этот проект не смотрели? https://zipcpu.com/blog/2023/11/25/eth10g.html


    1. pcbteach Автор
      07.12.2023 06:18

      На момент написания статьи этот проект не встретился, а на момент разработки кодеков его ещё не было. Модули были разработаны задолго до того, как появилась эта статья. Тогда мы и решили их выложить в github, так как не нашли готовых, хотя разработка их не была чем-то сложным. А теперь решили написать статью по этому поводу. Так что если кто воспользуется нашими наработками будет отлично =)


  1. m1kr1k
    07.12.2023 06:18

    У вас на схеме исходные 66 бит сжимаются до 64, а затем в декодере опять ппреобразуются в 66. Наверное, всё-таки, должно быть наоборот.


    1. pcbteach Автор
      07.12.2023 06:18

      На схеме всё указано верно.

      Возможно вы неверно поняли, идея конвертера не сжать данные, а из шины 66 бит перейти в шину 64 бита, так как, учитывая опыт использования высокоскоростных приёмопередатчиков, шина 66 бит обычно не доступна для выбора. Варианты зачастую такие 32,40,64 бит на такт. А при формировании и обработке данных с использованием кодека 66/64 удобно, когда за один такт сразу приходят данные 64 бита, и "служебка" 2 бита.