Як працює FIFO

FIFO це один з ключових елементів цифрової техніки. Це пам'ять типу «першим увійшов-першим пішов» (first input – first output). Мене як розробника ПЛІС FIFO оточують всюди. Власне я тільки і роблю, що беру дані з одного FIFO і перекладаю в інше. Але як воно працює? В сучасних САПР звичайно вже є готові елементи, у Altera є чудові мегафункции. У Xilinx є Core Generator. Але що робити, якщо щось не влаштовує в стандартних рішеннях? Відповідь одна – розібратися і написати самому.

В інтернеті існує велика кількість статей про FIFO, і коли мені попалася дуже гарна і розумна стаття. На жаль, зараз я її не знайшов. Далі – мій особистий досвід по створенню і застосуванню компонента FIFO. Готовий елемент знаходиться на Github в проекті fpga_components: github.com/dsmv/fpga_components
Свій компонент знадобився з кількох причин:
  1. FIFO XIlinx не вміє працювати в режимі ретрансмита – це головна причина
  2. FIFO Xilinx вимагає створення компонента з заданими параметрами – у нас розвелося занадто багато різних компонентів.
  3. FIFO Xilinx містить помилку – якщо приходить сигнал скидання одночасно з сигналом запису даних, то в FIFO застряє одне слово. Це ми звичайно обійшли, але все одно неприємно.
Отже, що таке FIFO. У загальному випадку це двопортова пам'ять, два лічильника адреси і два автомати – для читання і запису даних.



Одне з головних застосувань FIFO це перевід даних з однієї тактової частоти на іншу. Цим визначається така схема. При тактовій частоті на запис і читання автомати можна спростити.
Давайте розглянемо зовнішні порти компонента FIFO:
cl_fifo_m12
component is cl_fifo_m12 
generic(
FIFO_WIDTH : in integer:=64; -- ширина FIFO
FIFO_SIZE : in integer:=4096; -- розмір FIFO 
FIFO_PAF : in integer:=16; -- рівень спрацювання прапора PAF 
FIFO_PAE : in integer:=544 -- рівень спрацювання прапора PAE 
);
port( 
-- скидання
reset_p : in std_logic; -- 1 - скидання

-- запис
clk_wr : in std_logic; -- тактова частота
data_in : in std_logic_vector( FIFO_WIDTH-1 downto 0 ); -- дані
data_en : in std_logic; -- 1 - запис в fifo
flag_wr : out bl_fifo_flag; -- прапори fifo, синхронно з clk_wr
cnt_wr : out std_logic_vector( 15 downto 0 ); -- лічильник слів

-- читання
clk_rd : in std_logic; -- тактова частота
data_out : out std_logic_vector( FIFO_WIDTH-1 downto 0 ); -- дані

data_rd : in std_logic:='0'; -- 1 - читання з fifo, дані на другому такті
flag_rd : out bl_fifo_flag; -- прапори fifo, синхронно з clk_rd
cnt_rd : out std_logic_vector( 15 downto 0 ); -- лічильник слів


rt : in std_logic:='0'; -- 1 - перехід на початок в довільний момент
rt_mode : in std_logic:='0' -- 1 - перехід на початок після читання всього вмісту FIFO

);
end component;


Настроювання компонента:
  • FIFO_WIDTH – ширина FIFO, може бути будь-яка.
  • FIFO_SIZE – число слів у FIFO, це ступінь двійки, від 64 до 65536. Якщо потрібен більший розмір то треба робити складене FIFO.
  • FIFO_PAF – рівень спрацювання прапора майже повного FIFO.
  • FIFO_PAE – рівень спрацювання прапора майже порожнього FIFO, про прапори буде далі.
Назви портів цілком очевидні, кілька коментарів з прапорів:
Прапори FIFO передаються типом bl_fifo_flag; Визначення типу:
type bl_fifo_flag record is
ef : std_logic; -- 0 - FIFO порожнє
pae : std_logic; -- 0 - FIFO майже порожнє
hf : std_logic; -- 0 - FIFO заповнений наполовину 
paf : std_logic; -- 0 - FIFO майже повне
ff : std_logic; -- 0 - FIFO повне
ovr : std_logic; -- 1 - запис в повне FIFO
und : std_logic; -- 1 - читання з пустого FIFO
end record;

Зверніть увагу, використовується негативна логіка. Дізналися? Так, я ще з тих динозаврів хто працював з TTL на серіях 155, 533, 1533 і окремими мікросхемами FIFO. Так що ці прапори мені звичні, вони були зроблені багато років тому і до сих пір використовуються.
Прапор ef – сигналізує що FIFO порожнє. Якщо ef=1, то з FIFO можна прочитати одне слово.
Прапор pae – сигналізує, що FIFO майже порожнє. На скільки майже визначає параметр FIFO_PAE. Якщо pae=1, то з FIFO можна прочитати не більше ніж FIFO_PAE слів.
Прапор hf – сигналізує що FIFO заповнений наполовину.
Прапор впс – сигналізує, що FIFO майже повне. На скільки майже визначає параметр FIFO_PAF. Якщо paf=1, то в FIFO можна записати не більше ніж FIFO_PAF слів
Прапор ff – FIFO повне. Якщо ff=0, то в FIFO записувати не можна.
Прапор ovr – переповнення. Якщо ovr=1, то це означає що сталася запис у повне FIFO
Прапор und – underflow. Якщо und=1, то це означає що сталося читання з пустого FIFO.

Цілком очевидно, що при записі в FIFO ми повинні записати слово в двухпортовую пам'ять і збільшити лічильник запису. Або спочатку збільшити, а потім записати. А при операції читання треба зафіксувати дані на виході і збільшити лічильник читання. А от далі потрібно вирішити наступні питання:
  1. Як визначити що FIFO повна або не повна, тобто чи можна в нього записувати ?
  2. Як визначити що FIFO порожнє або не пусте? Тобто можна з нього читати ?
  3. Як правильно сформувати прапори PAE, PAF, HF ?
  4. Що таке число слів у FIFO ?
Цілком очевидно, що відповіді на всі ці питання у аналізі лічильників адреси для запису і читання. Але ці лічильники працюють на різних частотах. Ось тут починаються відмінності в реалізаціях. Я застосував симетричну схему передачі значень лічильників на інший тактовий домен. У результаті вийшло, що кожен з автоматів читання і запису має значення свого лічильника і затримане значення лічильника. З цих значень автомати формують свої прапори і значення кількості слів у FIFO. Це можна уявити на структурній схемі:



Треба ясно розуміти, що вузол перетактирования (в проекті це компонент ctrl_retack_counter_m12) передає дані з затримкою на кілька тактів. Тому стану FIFO також змінюються з затримкою. Наприклад, якщо FIFO порожнє і нього записано одне слово, то прапор ef=1 з'явиться з деякою затримкою. Це ж відноситься до виходів кількості слів у FIFO. Наприклад, якщо в порожнє FIFO буде записано 16 слів, то в процесі запису вихід cnt_wr буде приймати значення 0,1,2,3,… 16 (це якщо не проводиться читання з FIFO), а ось вихід cnt_rd буде приймати значення такі: 0, 5, 8, 12, 16. Точний порядок буде залежати від співвідношення частот і не може бути передбачений. Це принципова властивість FIFO яке працює на різних частотах. Хоча в залежності від схеми синхронізації можуть бути різні нюанси.
Визначення порожнього і повного FIFO проводиться на аналізі лічильників адрес. Причому у мене є дві адреси для запису (поточний і наступний) і дві адреси для читання, також поточний і наступний. У компоненті cl_fifo_control_m12 це сигнали w_adr, w_next_adr і r_adr, r_next_adr; Співвідношення адрес в різних станах представлено на малюнках нижче.
У вихідному стані w_adr=0, r_adr=0, w_next_adr=1, r_next_adr=1. Якщо w_adr=r_adr, то FIFO порожнє.



При записі слово даних записується за адресою w_adr та адресу запису збільшується.



Через кілька такий значення w_adr буде передано в w_adr_to_rd (перейде в тактовий домен clk_rd) і за фактом не збігу r_adr і w_adr_to_rd буде встановлено прапор ef=1, тобто з FIFO можна буде вважати слово даних. Проте одне слово це мало, для отримання високої швидкості передачі треба працювати з блоком даних. І тут потрібно використовувати прапор PAE. Коли в FIFO буде записано FIFO_PAE слів, буде встановлений прапор pae=1 і можна буде прочитати відразу блок даних. Це основний режим роботи з DMA каналом.
Якщо швидкість запису більше ніж швидкість читання, то адресу запису наздожене адреса читання:



У цьому випадку w_next_adr буде дорівнює r_adr, а точніше r_adr_to_wr (ми можемо порівнювати тільки значення на своєму тактовому домені). Це означає, що FIFO повне і записувати далі не можна, що б не зіпсувати вже записані дані. Треба зазначити, що для підключення АЦП це звичайна ситуація. У нас такий режим називається одноразовий збір через FIFO. У цьому режимі АЦП записує дані на великій швидкості в FIFO, а повільний процесор зчитує ці дані. При цьому ми знаємо, що дійсними тільки блок даних, який відповідає розміру FIFO. Зазвичай на цей розмір як раз і програмується канал DMA. Після читання даних FIFO скидається і все повторюється знову. Ось в цьому режимі принципово важливо, що б запис у повне FIFO не псувала попередні дані.
Якщо потрібно записувати дані блоками, то треба використовувати прапор ВПС. Якщо paf=1, то в FIFO можна записати FIFO_PAF слів.
Значення прапорів PAE і PAF треба вибирати з вимог DMA контролера до якого підключено FIFO. Наприклад, для PCI Express у нас використовується блок даних розміром 4 кБ. Це 256 слів по 128 розрядів. Розмір прапора PAE я встановлюю в 272. Тобто трохи більше ніж 256. Це я роблю свідомо, що б не допускати спустошення FIFO. Ну не довіряю я схемами формування прапорів.
А як проводиться визначення кількості слів у FIFO? Все досить просто – з адреси запису треба відняти адреса читання. Адреса кратний ступені 2, тому віднімання буде йти по модулю 2^N; Оскільки у нас є дві пари адрес, то у нас вийде і два значення кількості слів в одному FIFO (може це якось пов'язано з квантовою механікою?).
Значення прапорів PAE і HF (з читання) формуються з r_cnt. Значення PAF і HF(по запису) формуються з w_cnt.

Основною причиною, по якій довелося розробляти свій компонент FIFO, є потреба в реалізації циклічного режиму для роботи на ЦАП. В цьому режимі проводиться запис блоку даних, він може бути будь-якого розміру, зрозуміло не перевищуючи розміру FIFO. А потім починається читання, причому після видачі останнього записаного слова відразу відбувається перехід на перше слово. Це дозволяє підключити повільний процесор до швидкого ЦАП. Компонент FIFO має два входи для циклічного режиму. rt_mode=1 означає, що після видачі останнього записаного слова треба перейти на нульову адресу.
А от вхід rt потрібен трохи для іншого. Наявність rt=1 дозволяє перевести FIFO на нульову адресу в довільний момент часу. Іноді це у нас теж використовується.
У проекті fpga_components представлені два FIFO:
  • cl_fifo_x64_v7
  • cl_fifo_m12
cl_fifo_x64_v7 розроблено і опубліковано досить давно. Також він давно використовується і довів свою працездатність. Він як двухпортовой пам'яті використовує компонент сформований Core Generator. Для різних розмірів FIFO потрібні свої компоненти, наприклад в каталозі fpga_components\src\fifo\fifo_v7\coregen знаходяться чотири компоненти
  • ctrl_dpram512x64_v7
  • ctrl_dpram1024x64_v7
  • ctrl_dpram8192x64_v7
  • ctrl_dpram32768x64_v7
І це все тільки для шини з шириною 64 розряду. Для інших шин і інших розмірів потрібні свої компоненти. Ми їх потихеньку робили і до теперішнього моменту у нас є велика купа, з якою працювати вже незручно. Олександр Капітанів ( capitanov ) звернув на це увагу і запропонував елегантне рішення — зробити повністю синтезируемое FIFO. Він це реалізував у своєму проекті: github.com/capitanov/adc_configurator Компонент: ctrl_fifo_config
Основна ідея в тому, що б застосувати ось таку конструкцію VHDL:
type RAM is array (integer range <>) of std_logic_vector(DATA_WIDTH-1 downto 0);
signal Mem : RAM (0 to DATA_DEPTH-1);

Це конструкція буде синтезована в двухпортовую пам'ять.
Ідея гарна і в результаті доопрацювання cl_fifo_x64_v7 вийшло FIFO cl_fifo_m12

Недостатньо написати FIFO, треба ще перевірити його роботу. Для перевірки використовується підхід прийнятий при розробці PROTEQ, про який можна прочитати у моїй попередній статті.
Існує компонент tb_00 який має настроюються параметри.
tb_00
component is tb_00 
generic(
max_time : in time:=100 us; -- максимальний час тесту 
period_wr : in time; -- період частоти запису
period_rd : in time; -- період частоти читання
fifo_size : in integer; -- розмір FIFO 
FIFO_PAF : in integer; -- рівень спрацювання прапора PAF 
FIFO_PAE : in integer; -- рівень спрацювання прапора PAE 
max_fifo0_pkg : in integer-число пакетів для прийому

);
end component;


Він дозволяє перевірити проходження потоку даних через FIFO при різних співвідношеннях тактових частот і рівнях спрацьовування прапорів PAE і ВПС.
Також існують компоненти тестових випадків:
  • tc_00_01 – перевірять випадок, коли швидкість запису більше швидкості читання.
  • tc_00_02 – а це коли швидкість читання більше ніж швидкість запису.


В результаті формується ось такий звіт про запуск тестів:
Global fifo_12 TC log:
tc_00_01 PASSED
tc_00_02 PASSED

Звичайно, для кожного тесту зберігається і свій звіт.
Наприклад такий:
tc_00_01.log
# KERNEL: FIFO 0 - PKG= 1 6310 ns 0 ns ERROR: 0 SPEED: 0
# KERNEL: FIFO 0 - PKG= 2 12022 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 3 17734 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 4 23446 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 5 29158 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 6 34870 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 7 40582 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 8 46294 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 9 52006 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 10 57718 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 11 63430 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 12 69142 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 13 74854 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 14 80566 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 15 86278 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 16 91990 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 17 97702 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 18 103414 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 19 109126 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 20 114838 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 21 120550 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 22 126262 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 23 131974 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 24 137686 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 25 143398 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 26 149110 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 27 154822 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 28 160534 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 29 166246 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 30 171958 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 31 177670 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 32 183382 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 33 189094 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 34 194806 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 35 200518 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 36 206230 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 37 211942 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 38 217654 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 39 223366 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 40 229078 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 41 234790 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 42 240502 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 43 246214 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 44 251926 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 45 257638 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 46 263350 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 47 269062 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 48 274774 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 49 280486 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 50 286198 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 51 291910 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 52 297622 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 53 303334 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 54 309046 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 55 314758 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 56 320470 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 57 326182 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 58 331894 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 59 337606 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 60 343318 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 61 349030 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 62 354742 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 63 360454 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 64 366166 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 65 371878 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 66 377590 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 67 383302 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 68 389014 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 69 394726 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 70 400438 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 71 406150 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 72 411862 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 73 417574 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 74 423286 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 75 428998 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 76 434710 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 77 440422 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 78 446134 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 79 451846 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 80 457558 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 81 463270 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 82 468982 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 83 474694 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 84 480406 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 85 486118 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 86 491830 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 87 497542 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 88 503254 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 89 508966 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 90 514678 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 91 520390 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 92 526102 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 93 531814 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 94 537526 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 95 543238 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 96 548950 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 97 554662 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 98 560374 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG= 99 566086 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=100 571798 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=101 577510 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=102 583222 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=103 588934 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=104 594646 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=105 600358 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=106 606070 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=107 611782 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=108 617494 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=109 623206 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=110 628918 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=111 634630 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=112 640342 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=113 646054 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=114 651766 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=115 657478 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=116 663190 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=117 668902 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=118 674614 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=119 680326 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=120 686038 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=121 691750 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=122 697462 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=123 703174 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=124 708886 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=125 714598 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=126 720310 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=127 726022 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=128 731734 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=129 737446 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=130 743158 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=131 748870 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=132 754582 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=133 760294 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=134 766006 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=135 771718 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=136 777430 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=137 783142 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=138 788854 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=139 794566 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=140 800278 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=141 805990 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=142 811702 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=143 817414 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=144 823126 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=145 828838 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=146 834550 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=147 840262 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=148 845974 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=149 851686 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=150 857398 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=151 863110 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=152 868822 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=153 874534 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=154 880246 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=155 885958 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=156 891670 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=157 897382 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=158 903094 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=159 908806 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=160 914518 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=161 920230 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=162 925942 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=163 931654 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=164 937366 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=165 943078 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=166 948790 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=167 954502 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=168 960214 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=169 965926 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=170 971638 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=171 977350 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=172 983062 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=173 988774 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=174 994486 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=175 1000198 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=176 1005910 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=177 1011622 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=178 1017334 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=179 1023046 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=180 1028758 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=181 1034470 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=182 1040182 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=183 1045894 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=184 1051606 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=185 1057318 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=186 1063030 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=187 1068742 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=188 1074454 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=189 1080166 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=190 1085878 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=191 1091590 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=192 1097302 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=193 1103014 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=194 1108726 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=195 1114438 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=196 1120150 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=197 1125862 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=198 1131574 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=199 1137286 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=200 1142998 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=201 1148710 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=202 1154422 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=203 1160134 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=204 1165846 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=205 1171558 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=206 1177270 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=207 1182982 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=208 1188694 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=209 1194406 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=210 1200118 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=211 1205830 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=212 1211542 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=213 1217254 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=214 1222966 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=215 1228678 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=216 1234390 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=217 1240102 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=218 1245814 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=219 1251526 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=220 1257238 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=221 1262950 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=222 1268662 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=223 1274374 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=224 1280086 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=225 1285798 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=226 1291510 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=227 1297222 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=228 1302934 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=229 1308646 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=230 1314358 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=231 1320070 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=232 1325782 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=233 1331494 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=234 1337206 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=235 1342918 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=236 1348630 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=237 1354342 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=238 1360054 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=239 1365766 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=240 1371478 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=241 1377190 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=242 1382902 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=243 1388614 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=244 1394326 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=245 1400038 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=246 1405750 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=247 1411462 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=248 1417174 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=249 1422886 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=250 1428598 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=251 1434310 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=252 1440022 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=253 1445734 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=254 1451446 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=255 1457158 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: FIFO 0 - PKG=256 1462870 ns 5712 ns ERROR: 0 SPEED: 1368
# KERNEL: Завершено прийом даних: 1463200 ns
# KERNEL: FIFO 0 
# KERNEL: Прийнято пакетів: 256
# KERNEL: Правильних: 256
# KERNEL: Помилкових: 0
# KERNEL: Загальне число помилок: 0
# KERNEL: Швидкість передачі: 1368 МБайт/с
# KERNEL: 
# KERNEL: 
# KERNEL: 
# KERNEL: TEST finished successfully
# KERNEL:


При необхідності тести будуть доповнюватися.
Хочу звернути увагу, що для виведення тексту в консоль я використовую пакет PCK_FIO. Він різко спрощує вивід тексту.
Наприклад, виведення результатів виглядає так:
fprint( output, L, "Завершено прийом даних: %r ns\n", fo(now) );
fprint( output, L, "FIFO 0 \n" );
fprint( output, L, " Прийнято пакунків: %d\n", fo( rx0_result.pkg_rd ) );
fprint( output, L, " Правильних: %d\n", fo( rx0_result.pkg_ok ) );
fprint( output, L, " Помилкових: %d\n", fo( rx0_result.pkg_error ) );
fprint( output, L, " Загальне число помилок: %d\n", fo( rx0_result.total_error ) );
fprint( output, L, " Швидкість передачі: %r МБайт/с\n\n", fo( integer(rx0_result.velocity) ) );

Це схоже на Сі.

У підсумку я вважаю що вийшов елегантний компонент, досить зручний для практичної роботи.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.