Реализация кодека 66b/64b на языке VHDL

Автор: https://github.com/iwaniwaniwan012

Введение

В протоколах передачи данных для стабильной работы используются кодеки, выбранные разработчиками с учётом следующих требований:

  • равномерное распределение 0 и 1 в канале

  • простота кодирования/декодирования

  • иметь небольшую избыточность

Один из самых распространённых протоколов, о которых думаю, если не каждый человек, то уж каждый инженер точно слышал, является Ethernet, который имеет большое количество стандартов. Он так же использует кодек, а именно 66b/64b, который широко известен в инженерных кругах. Вот небольшой список популярных протоколов, использующих этот кодек:

Общее описание кодека 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 бит и наоборот.

Итоговая схема работы всего нашего проекта получается следующая:

bcmrx3xy2mcfiekfnstgjmxyrqq.png

Алгоритм работы модулей

Конвертеры

Представляют из себя сдвиговый регистр, который в зависимости от текущего наполнения, выдаёт сдвинутые данных.

Проще говоря сдвиговый регистр и мультиплексор.

Синхронизатор

Алгоритм синхронизации состоит в следующем:

  • Поиск синхронизации осуществляется за счёт объединения двух шин, представляющих из себя данные, полученные на предыдущем такте и на текущем такте.

  • Если 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 бита сдвигового регистра, а так же каждого входного бита данных, от младшего к старшему.

ke9_olkhro4vipg_td2vqnrlw7q.pngk3zteebbn3vmkbubkxdhl5aq3du.png

Описание алгоритма на 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.

ssmtsijsmuvek9svqmoepaz_ybo.png

Требуемые ресурсы ПЛИС и максимальная частота

При разработке различных модулей ПЛИС, перед использованием их в реальном проекте, мы используем тестовый проект с внутренним названием 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. Комментарии и пожелания крайне приветствуются =)

© Habrahabr.ru