nabbla (nabbla1) wrote,
nabbla
nabbla1

Categories:

Юнит-тест модуля управления видеопроцессором

Этот модуль я написал 30 июля, и как там написано - тестировать особо не стал. Казалось, что "в обвязке" оно будет проще, чем ручками придумывать все поступающие на него сигналы. Вот теперь увидели "в обвязке", на вполне конкретном сценарии он не заработал, и сейчас выведем дополнительную "отладочную" информацию и разберёмся, что с ним не так.



И через минуту после появления этой "осциллограммы" удалось найти ошибку. Она была пустяковой, как это чаще всего и бывает...


Мы повторили ситуацию, которая сложилась на симуляции всей сборки: сначала видеопроцессор "отдыхает" без заданий и без синхроимпульсов, потом мы закидываем туда одно задание на кадровый синхроимпульс (VSync) и десяток заданий на строчный синхроимпульс (HSync), из-за чего буфер забивается - и процессор уходит в ожидание. И только потом эти импульсы приходят сразу оба, как автобусы на остановку после часового перерыва.

А наблюдаем мы за самым первым словом, содержащемся в буфере, которое непосредственно прочитывает "модуль управления" и работает по нему. Это сигналы DBuf (Debug Buffer), здесь содержится координата X, до которой надо вести измерения, DSync (Debug Sync) - это два бита, выражающие режим синхронизации. 00 - ждать синхроимпульсов не надо, 01 - нужен строчный, 10 - нужен кадровый, 11 - у нас пришло отрицательное число, ждать не надо вообще ничего - выдаём ноль и идём дальше! И ещё isSum - режим работы, обнаружение (найти самый яркий пиксель) или сопровождение (найти яркостный центр с субпиксельной точностью). isSum - значит сопровождение (вычисляется две суммы, а дальше дело за QuatCore).

Ещё мы смотрим на управляющие сигналы, которые модуль управления подаёт в "Data Path". Это start (обнуление вычислителей и одновременно выдача их последних результатов в выходной буфер), flush (сброс выходного буфера), SrcStallReq (запрос на остановку QuatCore, пока входной буфер переполнен) и UFLO (грязно выругаться зелёным светодиодиком "оператору макета", что он пожадничал на длине буфера, и видеопроцессор упустил часть строки, ничего с ней не сделав).

UFLO сработал ровно также, как на симуляции "всей сборки", постоянство признак мастерства :)
SrcStallReq тоже, в общем-то не удивил почти: когда буфер переполнился и у нас зафиксировалось SrcStallReq=1 - это всё верно, мы это наблюдали и на сборке. Довольно длинный комбинаторный "пичок" напрягает, но до фронта он исчезает, а значит, жить можно.

Ошибка прослеживается в сигнале DSync. Как видно, туда защёлкивается двойка (двоичные 10), что означает ожидание кадрового синхроимпульса. Когда этот импульс придёт, единичка должна сброситься, что и позволит видеопроцессору "сдвинуться с места", но там осталась двойка.

И вот дефектный код, который привёл к проблеме, в модуле FIFO_on_LE_for_GPU:

if (ena[0]) begin
		DR[0][DataWidth-1] <= Vsync? 1'b0 : CR[1]? D[DataWidth-1] : DR[1][DataWidth-1];	
		DR[0][DataWidth-2] <= Hsync? 1'b0 : CR[1]? D[DataWidth-2] : DR[1][DataWidth-2];
		DR[0][DataWidth-3:0] <= CR[1]? D[DataWidth-3:0] : DR[1][DataWidth-3:0];
	end;


Я поставил HSync и VSync в самое начало соответствующей строки, чтобы именно эти сигналы были "самыми приоритетными" для данных бит, но забыл, что всё это сидит внутри блока "if", то есть вход разрешения работы ena[0] оказывается наиболее приоритетным! А в нашем случае оказывается ena[0]=0, поскольку запроса на чтение от блока управления не поступает (зачем приступать к следующей команде, если и эту ещё не обработали?), и запроса на запись конкретно этой ячейки поступить не может, поскольку она пока занята! Вот и всё - синхросигналы канули в Лету...

Что ж, исправляем:
	if (ena[0] | Vsync)
		DR[0][DataWidth-1] <= Vsync? 1'b0 : CR[1]? D[DataWidth-1] : DR[1][DataWidth-1];
	if (ena[0] | Hsync)	
		DR[0][DataWidth-2] <= Hsync? 1'b0 : CR[1]? D[DataWidth-2] : DR[1][DataWidth-2];
	if (ena[0])
		DR[0][DataWidth-3:0] <= CR[1]? D[DataWidth-3:0] : DR[1][DataWidth-3:0];


Синтезируем, снова запускаем симуляцию:


ВОТ ЭТО УЖЕ ПОЛУЧШЕ! По приходу синхроимпульсов Sync с двойки сбросилось в ноль, и на следующий же такт сформировался импульс start. Вслед за этим на выходах DSync и DBuf зафиксировались значения со следующего запроса - теперь нам нужен строчный синхроимпульс (DSync=1), а вслед за ним ещё 240 тактов на BackPorch (DBuf=0xF0).


Пора возвращаться к отладке ВСЕГО ДРАНДУЛЕТА, и посмотреть, насколько далеко удастся уйти.
Tags: ПЛИС, программки, работа, странные девайсы
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments