1. Разглядывая JTAG: идентификация

  2. Разглядывая JTAG: *.bsdl своими руками

В предыдущей статье мы немного поработали с конечным автоматом модуля JTAG в контексте чтения идентификационного номера. Совершённые нами манипуляции были бы одинаковы практически для любой микросхемы с JTAG-ом. Однако при попытке установить/считать через JTAG уровень напряжения на произвольном выводе микросхемы мы столкнёмся с объективной проблемой: количество выводов, их назначение и расположение у разных микросхем принципиально отличаются. Для того, чтобы у ПО, управляющего JTAG-ом была информация об этих отличиях, ему необходим файл описания модуля JTAG для конкретной микросхемы. Об этих файлах и пойдёт речь в данной статье.

Файл *.bsdl содержит ряд параметров модуля JTAG. Сейчас, в 2022 году может показаться, что разумнее всего было бы использовать для подобной цели нечто вроде XML. Проблема в том, что первый стандарт JTAG — IEEE1149.1 — был выпущен в 1990 году, тогда как XML 1.0 появился лишь в 1998. При современном взгляде на текст файла *.bsdl можно уловить, во-первых, схожесть его синтаксиса с VHDL, во-вторых, избыточность и многословность даже для тех времён. К примеру, при указании длины регистра инструкций можно было бы ожидать чего-то вроде...

entity SIMPLE_IC is
	<...>
	INSTRUCTION_LENGTH	4
	<...>
end SIMPLE_IC;

...или хотя бы...

entity SIMPLE_IC is
	<...>
	attribute INSTRUCTION_LENGTH = 4;
	<...>
end SIMPLE_IC;

Но по стандарту длина регистра инструкций задаётся так:

entity SIMPLE_IC is
	<...>
	attribute INSTRUCTION_LENGTH of SIMPLE_IC : entity is 4;
	<...>
end SIMPLE_IC;

Дело в том, что BSDL появился в стандарте JTAG не сразу в 1990 году, а начиная с версии IEEE1149.1B-1994. До его появления управляющее ПО получало информацию о структуре модуля JTAG напрямую из файлов описания микросхемы, написанных на VHDL. То есть BSDL скорее формализовал действующую на тот момент практику, чем был специально, с нуля, разработан для использования в качестве языка описания модуля JTAG.

За дополнительными разъяснениями я обратился к Кэролу Пайрону (Carol Pyron), представителю от NXP в группе JTAG и, по совместительству, вице-председателю данной группы:

- Добрый день, мистер Пайрон! Почему в качестве основы языка BSDL был взят VHDL?

- Добрый день. Я не принимал непосредственного участия в разработке первой выпущенной версии BSDL, поэтому я не могу вам дать определённый ответ, но я помню, мне говорили, что многие европейские и американские аэрокосмические компании в конце 80-х — начале 90-х использовали VHDL гораздо чаще, чем Verilog. Поскольку большинство людей, участвовавших в разработку BSDL, имели именно такой бэкграунд, был выбран именно этот язык. Конечно, с тех пор Verilog стал намного более распространённым и доминирующем.

Оригинал моей переписки на английском

- Hello, mr. Piron. May I ask you why VHDL was chosen as the base syntax for BSDL?

- Hello. I was not directly involved in the original version of BSDL, so I cannot give you a definitive answer, but I remember being told that VHDL was always more used by many European companies and by American aerospace companies back in the late 80's/ early 90's than Verilog. Since most of the people involved in BSDL had that background, VHDL was selected. Of course since then, Verilog has become much more common and dominate.

На текущий момент в ряде синтаксических конструкций BSDL уже нет прежнего сакрального смысла и обратная совместимость 30-летней давности, возможно, будет несколько резать глаза. Но с этим придётся смириться.

Итак. Всё описание модуля JTAG находится между декларацией имени микросхемы и окончанием описания:

entity SIMPLE_IC is
	--Описание модуля JTAG
end SIMPLE_IC;

Сразу после декларации имени нужно вписать параметр для указания конкретного корпуса:

generic (PHYSICAL_PIN_MAP : string);

Его можно оставить незаполненным, а можно вписать туда какой-нибудь из корпусов, которые будут описаны далее в файле BSDL:

generic (PHYSICAL_PIN_MAP : string := "PLCC20");

Выбор, сделанный в данной декларации, не повлияет на работу с файлом в «TopJTAG Probe» и в данном ПО можно будет выбрать конкретный корпус независимо от указанного в «generic». Однако, по стандарту данная декларация должна присутствовать.

Затем необходимо указать общую структуру входов-выходов, их названия и тип. То, что описывается в разделе «port» — это не совсем выводы микросхемы. Скорее, это контактные площадки кристалла, хотя и это, строго говоря, не совсем верно. Это, скажем так, все возможные контакты микросхемы, описанные с некоторым запасом (чуть дальше будет яснее). В блоке «port» необходимо указать как «полезные» контакты микросхемы, так и контакты самого JTAG, а также контакты питания, земли и отсутствующие контакты — контакты, которые не предполагается соединять с кристаллом:

port  (
	LED: out bit_vector(0 to 7);
	BTN: in  bit_vector(0 to 7);

	TMS: in  bit;
	TDI: in  bit;
	TCK: in  bit;
	TDO: out bit;

	VDD: linkage bit;
	VSS: linkage bit;
	NC:  linkage bit_vector(0 to 9)
);

Здесь всё более-менее интуитивно понятно. Если вывод одиночный — он помечается как «bit». Если это шина, она помечается как «bit_vector(X to Y)». Входы — «in», выходы — «out», двунаправленные линии — «inout».

Линии питания/земли, а также аналоговые входы-выходы и выводы, не соединённые с кристаллом, стандарт настоятельно рекомендует помечать как «linkage». В стандарте IEEE1149.1-2013 вместо «linkage» вводится 10 новых типов вроде «POWER_POS» или «LINKAGE_MECHANICAL». Однако «TopJTAG Probe» их не распознаёт. Кроме того, файлы BSDL, написанные по стандарту 2013 года на текущий момент гораздо менее распространены, чем файлы предыдущих версий стандарта, поэтому мы будем рассматривать, по большей части, версию стандарта 2001 года.

После блока «port» стандарт требует подключить библиотеку стандарта JTAG:

use STD_1149_1_2001.all;

Этой библиотеки у нас нет, но это и не важно — данная строка просто один из рудиментов VHDL.

Итого, подготовительные процедуры приведут нас к следующему коду:

entity SIMPLE_IC is
	generic (PHYSICAL_PIN_MAP : string);
	port  (
		LED:	out bit_vector(0 to 7);
		BTN:	in  bit_vector(0 to 7);
		TMS:	in  bit;
		TDI:	in  bit;
		TCK:	in  bit;
		TDO:	out bit;
		VDD:	linkage bit;
		VSS:	linkage bit;
		NC:	linkage bit_vector(0 to 9)
		);
	use STD_1149_1_2001.all;
	--Атрибуты модуля JTAG
end SIMPLE_IC;

Теперь нам необходимо заполнить некоторое количество атрибутов модуля JTAG. В общем случае, для отдельного атрибута это заполнение будет выглядеть так:

attribute XXX of SIMPLE_IC : entity is YYY;

Последовательность заполнения атрибутов крайне нежелательно изменять. Но некоторые из атрибутов являются необязательными. Их можно пропустить. К примеру, атрибут «RUNBIST_EXECUTION» мы заполнять не будем.

Первым атрибутом будет версия стандарта JTAG. Да-да, мы, уже подключили библиотеку с этим самым названием стандарта, но так надо:

attribute COMPONENT_CONFORMANCE of SIMPLE_IC : entity is "STD_1149_1_2001";

Затем нам необходимо заполнить атрибут «PIN_MAP» не особо осмысленной строкой:

attribute PIN_MAP of SIMPLE_IC : entity is PHYSICAL_PIN_MAP;

А дальше уже интереснее:

constant  PLCC20:PIN_MAP_STRING:=
	"LED:	(1,2,3,4), " &
	"BTN:	(8,7,6,5), " &
	"TMS:	9, " &
	"TDI:	10, " &
	"TCK:	11, " &
	"TDO:	12, " &
	"VDD:	13, " &
	"VSS:	14, " &
	"NC:	(15,16,17,18,19,20) ";

В этой конструкции описывается конкретный корпус микросхемы. После слова «constant» указывается его название, а затем контакты из раздела «port» распределяются по выводам корпуса. Программа «TopJTAG Probe» способна распознать некоторые названия корпусов и подобрать соответствующее схематическое изображение.

Распределение одиночных контактов достаточно прозрачно: один контакт — один вывод. Распределение шин (векторов) происходит в порядке очерёдности контактов в шине. Причём допускается распределить не все контакты из раздела «port».

Стандарт допускает указание нескольких подобных блоков в рамках одного файла BSDL:

constant  PLCC20:PIN_MAP_STRING:=
	"LED:	(1,2,3,4), " &
	<...>
	"NC:	(15,16,17,18,19,20) ";
constant  TQFP32:PIN_MAP_STRING:=
	"LED:	(1,2,3,4,5,6,7,8), " &
	<...>
	"NC:	(29,30,31,32) ";

В таком случае «TopJTAG Probe» не сможет определить нужный корпус автоматически (даже если он был задан в «generic»), но его можно будет выбрать из меню.

Для того, чтобы выбрать в «TopJTAG Probe» определённый тип корпуса надо:

  1. Выбрать пункт меню «Scan→ Dev1 Package...»

  2. В открывшемся окне выбрать тип из списка.

  3. Нажать «Select» для автоопределения типа, количества выводов и их расположения. Затем нажать «OK».

Также, в «TopJTAG Probe» возможно указать параметры корпуса вручную, не прибегая к автоопределению по названию корпуса.

Далее нам нужно задать атрибуты, привязывающие контакты, указанные в разделе «port» к выводам JTAG, а также указать максимальную частоту тактового сигнала TCK. В нашем примере — это 10кГц.

attribute TAP_SCAN_MODE  of TMS : signal is true;
attribute TAP_SCAN_IN    of TDI : signal is true;
attribute TAP_SCAN_CLOCK of TCK : signal is (10.0e3, BOTH);
attribute TAP_SCAN_OUT   of TDO : signal is true;

Следующие атрибуты — особенно важны. В предыдущей статье помимо регистра данных, мы создавали 8-битный регистр инструкций, инициализируемый нулём. Для каждой конкретной модели микросхем длина этого регистра фиксирована. Однако у разных моделей эта длина будет разная. Длина регистра инструкций задаётся при помощи следующего атрибута:

attribute INSTRUCTION_LENGTH of SIMPLE_IC : entity is 8;

Также нам нужно описать сами инструкции и их коды. В ряде источников говорится, что существуют обязательные стандартные инструкции, необязательные стандартные инструкции и уникальные инструкции конкретного производителя микросхем. Надо отметить, что по поводу «обязательных» инструкций стандарт говорит следующее:

The following public instructions shall be provided in all components claiming conformance to this standard: BYPASS, SAMPLE, PRELOAD, and EXTEST. If the optional device identification register is included in a component, the IDCODE instruction shall be provided.

Именно «shall», а не «must». Это значит, что наличие данных инструкций — настоятельно рекомендовано, но не строго обязательно. К слову, как и наличие 32‑битного идентификационного кода, которого по стандарту может и не быть! Собственно, «TopJTAG Probe» без проблем воспринимает файл BSDL, в котором атрибут, описывающий идентификационный код отсутствует, а из всех инструкций имеется лишь «MY_INSTRUCTION». Тем не менее, в подавляющем большинстве микросхем, поддерживающих JTAG, имеются, как минимум, 4 инструкции: «IDCODE», «BYPASS», «EXTEST» и «SAMPLE/PRELOAD».

Не углубляясь сейчас в предназначение инструкций «EXTEST» и «SAMPLE/PRELOAD», поговорим про «IDCODE» и «BYPASS».

Представим, что у нас имеется цепь из 3-х микросхем. Каким образом мы сможем за наиболее короткое время определить идентификационный номер первой микросхемы в цепи?

Мы можем действовать также, как в предыдущей статье:

  1. Подадим 5 единиц по TMS и введём все микросхемы цепи в состояние «TEST LOGIC RESET». Это займёт 5 тактов.

  2. Переведём все микросхемы цепи в состояние «SHIFT DR». Это займёт ещё 4 такта.

  3. Протактируем полный сдвиг 32-битных регистров идентификационного кода трёх микросхем — два регистра микросхем, находящихся за интересующей нас микросхемой, плюс, собственно, интересующий нас регистр. То есть 32х3=96 тактов.

Итого: 105 тактов.

Однако, мы можем поступить и иначе:

  1. Подадим 5 единиц по TMS и введём все микросхемы цепи в состояние «TEST LOGIC RESET» — 5 тактов.

  2. Переведём все микросхемы цепи в состояние «SHIFT IR» — 5 тактов.

  3. Размер регистра инструкций произволен, но часто составляет 3-4 бита. Пускай, для 3-х микросхем нашей воображаемой цепи длина регистров инструкций будет 8 бит, 5 бит и 3 бита. Итого — 16 бит. Составим такой 16-битный пакет, в котором в начале будет 3‑битный код инструкции «BYPASS» третей микросхемы, затем 5‑битный код инструкции «BYPASS» второй микросхемы и, наконец, 8‑битный код инструкции «IDCODE» первой микросхемы. Отметим, что для различных микросхем коды инструкции «BYPASS» могут различаться.

  4. Введём эту последовательность через TDI. Это займёт у нас «16-1» тактов (почему «-1» разберёмся позже). Длина регистра инструкций для каждой конкретной микросхемы является строго фиксированной величиной. А вот длина регистра данных — нет. И, вводя определённые коды в регистр инструкций, совершенно различные регистры разной длины могут подключаться в качестве регистра данных. В частности, код инструкции «IDCODE» подключает в качестве регистра данных 32-битный регистр, заполненный идентификационным кодом, а код инструкции «BYPASS» подключает в качестве регистра данных регистр длиной 1 бит, заполненный нулём.

  5. Теперь переведём все микросхемы цепи из состояния «SHIFT IR» в состояние «SHIFT DR». На это уйдёт 5 тактов.

  6. И, наконец, протактируем два бита регистров «BYPASS» двух микросхем, стоящих перед целевой, а также 32 бита идентификационного кода. На это уйдёт ещё 34 такта.

Итого: 64 такта.

Быстрее на 40%. Очевидно, чем больше микросхем в цепи, тем выгоднее использовать инструкцию «BYPASS».

Вернёмся к заполнению файла BSDL. Чтобы присвоить коды инструкциям, заполним следующий атрибут:

attribute INSTRUCTION_OPCODE of SIMPLE_IC : entity is
	"IDCODE (00000001)," &
	"EXTEST (00000010)," &
	"BYPASS (00000011)," &
	"SAMPLE (00000100) ";

Двух команд с одинаковым кодом быть не должно. Однако, одной команде можно присвоить несколько разных кодов. Например, так:

"BYPASS (00000011,00000111,0001XXXX)," &

Здесь «X» будет пометкой для управляющего ПО, что значения бит на этих позициях могут быть любые.

В прошлой статье мы инициализировали регистр инструкций нулём. Причём делали это в состоянии «TEST LOGIC RESET». В реальности, регистр инструкций инициализируется в состоянии «CAPTURE IR». В файле BSDL указывается, чем именно инициализируется регистр инструкций:

attribute INSTRUCTION_CAPTURE of SIMPLE_IC : entity is "0000001";

Однако есть ограничение стандарта: младший бит обязательно должен быть единицей, а следующий бит — нулём, то есть в начале инициализирующего значения должно стоять «01».

Заполним атрибут файла BSDL, отвечающий за идентификационный номер тем же числом h0AA55003, что использовали в предыдущей статье:

attribute IDCODE_REGISTER of SIMPLE_IC : entity is
	"0000" &             -- код ревизии или чего-нибудь типа того
	"1010101001010101" & -- код модели микросхемы hAA55
	"00000000001" &      -- код производителя (соответствует AMD)
	"1";                 -- единица по стандарту IEEE1149.1

Как указывалось выше, различные коды, помещаемые в регистр инструкций, способны подключить в качестве регистра данных различные внутренние регистры. Помимо подключаемых регистров, с которыми мы работали чуть выше — «BYPASS» и «DEVICE_ID» — в модуле JTAG имеется, если так можно выразиться, самый главный подключаемый регистр — «BOUNDARY». Какая именно инструкция подключит в качестве регистра данных какой именно регистр — определяет атрибут «REGISTER_ACCESS»:

attribute REGISTER_ACCESS of SIMPLE_IC : entity is
	"DEVICE_ID (IDCODE)," &
	"BYPASS   (BYPASS)," &
	"BOUNDARY (EXTEST, SAMPLE)";

По аналогии с инструкциями, которые могут быть стандартными, а могут быть уникальными для конкретного производителя микросхем (или конкретной модели), также и подключаемые регистры модуля JTAG могут не ограничиваться списком из «DEVICE_ID», «BYPASS» и «BOUNDARY». И, введя в атрибуте «INSTRUCTION_OPCODE» инструкцию «MY_INSTRUCTION», можно в атрибуте «REGISTER_ACCESS» сообщить управляющему ПО о желании подключать нестандартный регистр, если соответствующая инструкция была загружена в регистр инструкций:

attribute REGISTER_ACCESS of SIMPLE_IC : entity is
	<...>
	"MY_REG[8] (MY_INSTRUCTION)," & -- здесь «8» это длина регистра
	<...>

Кроме того, в данном атрибуте можно указать, каким значением должен быть проинициализирован подключаемый регистр при попадании модуля JTAG в состояние «CAPTURE DR»:

"MY_REG[8] (MY_INSTRUCTION CAPTURES 01010101)," &

Однако, по поводу данного атрибута стандарт говорит следующее:

The association of registers with the BYPASS, CLAMP, EXTEST, HIGHZ, IDCODE, INTEST, PRELOAD, SAMPLE, and USERCODE instructions is mandated by this standard. Descriptions of these assignments are redundant and not needed in BSDL. But if they are given, they shall be checked against the mandatory assignment specified in this standard and an error issued if they are not correct; and they shall not have a “CAPTURES” element in their description.

Иными словами, для стандартных инструкций используются стандартные подключаемые регистры и их явное соотнесение в файле BSDL будет носить скорее справочно‑декоративный характер. Поэтому у ряда микросхем атрибут «REGISTER_ACCESS» будет заполнен не для всех инструкций и подключаемых регистров, а программа «TopJTAG Probe» принимает на вход файлы BSDL даже с отсутствующим атрибутом «REGISTER_ACCESS». Но если мы всё-таки решим расписать данный атрибут полностью, то метка «CAPTURE» с указанием значения по умолчанию в стандартных подключаемых регистрах будет являться синтаксической ошибкой.

Наконец мы подходим к атрибутам самого главного подключаемого регистра. JTAG наиболее известен возможностью при помощи четырёх проводов «пошевелить» практически любым выводом микросхемы. Соответственно, где-то внутри модуля JTAG должна иметься структура, отвечающая за каждый доступный вывод микросхемы. Такой структурой является подключаемый регистр «BOUNDARY».

Для начала нам потребуется задать длину данного регистра:

attribute BOUNDARY_LENGTH of SIMPLE_IC : entity is 8;

А затем — связать доступные для манипуляций выводы микросхемы с битами данного регистра:

attribute BOUNDARY_REGISTER	of SIMPLE_IC : entity is
	"0 (BC_1, LED(0), output2, X)," &
	"1 (BC_1, LED(1), output2, X)," &
	"2 (BC_1, LED(2), output2, X)," &
	"3 (BC_1, LED(3), output2, X)," &
	"4 (BC_1, BTN(0), input,   X)," &
	"5 (BC_1, BTN(1), input,   X)," &
	"6 (BC_1, BTN(2), input,   X)," &
	"7 (BC_1, BTN(3), input,   X)" ;

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

  • Номер бита в регистре «BOUNDARY»

  • Типовая группа контактов. В стандарте данный параметр называется странным термином <cell name>. На самом деле, крайне непрозрачный параметр, о котором надо знать, пожалуй, две вещи: если у вас двунаправленный вывод, то этот параметр следует записать, как «BC_7», в иных случаях — как «BC_1»

  • Наименование контакта микросхемы из раздела «port». В случае шины следует также указать номер линии в шине.

  • Тип контакта. В простейшем случае — это «input» или «output2» («...2» символизирует два возможных состояния линии).

  • Безопасное значение. В простейшем случае данный параметр указывается как «X», что означает, что любое значение на выходе данного контакта — безопасное.

Более сложное описание связи для типов контактов «bidir» и «output3» выглядит так:

"42 (BC_7, MY_BUS(0), bidir, X, 44, 1, Z)," &
"43 (BC_7, MY_BUS(1), bidir, X, 44, 1, Z)," &
"44 (BC_1, *, control, 1)," &

Как видно, 42-й бит регистра «BOUNDARY» связан с нулевой линией двунаправленной шины «MY_BUS». У этого описания связи, помимо 5-и уже упомянутых параметров появляется три дополнительных:

  • Номер бита в регистре «BOUNDARY», который способен повлиять на выход линии «MY_BUS(0)». К примеру, перевести её в высокоимпедансное состояние. В данном случае — это 44-й бит.

  • Конкретное значение 44-ого бита при котором это влияние будет осуществлено.

  • Тип влияния. Буква «Z» означает перевод в высокоимпедансное состояние. Но также в стандарте предусмотрен ряд иных типов влияния. К примеру, «KEEPER». В случае применения данного типа влияния, контакт «MY_BUS(0)» сохранит предыдущее значение, даже если содержимое 42-ого бита, привязанного к контакту изменится.

Логично предположить, что в вышеописанном случае 44-й бит может быть не привязан к какому-либо контакту. Поэтому, тип подобных битов устанавливается в «control», а вместо наименования контакта ставится символ «*». В подавляющем большинстве случаев, битам, переводящим контакты в высокоимпедансное состояние явно задаётся такое безопасное значение, при котором эти контакты гарантированно окажутся в состоянии «HiZ». Так же из вышеприведённого примера видно, что один управляющий бит способен оказывать влияние сразу на несколько контактов.

Собрав все элементы вместе, мы получим следующий файл BSDL:
entity SIMPLE_IC is
	generic (PHYSICAL_PIN_MAP : string);
	port  (
		LED: out bit_vector(0 to 7);
		BTN: in  bit_vector(0 to 7);
		TMS: in  bit;
		TDI: in  bit;
		TCK: in  bit;
		TDO: out bit;
		VDD: linkage bit;
		VSS: linkage bit;
		NC:  linkage bit_vector(0 to 9)
		);

	use STD_1149_1_2001.all;

	attribute COMPONENT_CONFORMANCE of SIMPLE_IC : entity is "STD_1149_1_2001";
	attribute PIN_MAP of SIMPLE_IC : entity is PHYSICAL_PIN_MAP;

	constant  PLCC20:PIN_MAP_STRING:=
		"LED:	(1,2,3,4), " &
		"BTN:	(8,7,6,5), " &
		"TMS:	9, " &
		"TDI:	10, " &
		"TCK:	11, " &
		"TDO:	12, " &
		"VDD:	13, " &
		"VSS:	14, " &
		"NC:	(15,16,17,18,19,20) ";

	attribute TAP_SCAN_MODE	of TMS : signal is true;
	attribute TAP_SCAN_IN		of TDI : signal is true;
	attribute TAP_SCAN_CLOCK	of TCK : signal is (10.0e3, BOTH);
	attribute TAP_SCAN_OUT		of TDO : signal is true;

	attribute INSTRUCTION_LENGTH of SIMPLE_IC : entity is 8;
	attribute INSTRUCTION_OPCODE of SIMPLE_IC : entity is
		"IDCODE (00000001)," &
		"EXTEST (00000010)," &
		"BYPASS (00000011)," &
		"SAMPLE (00000100) ";
	attribute INSTRUCTION_CAPTURE of SIMPLE_IC : entity is "00000001";

	attribute IDCODE_REGISTER of SIMPLE_IC : entity is
		"0000" &             -- код ревизии или чего-нибудь типа того
		"1010101001010101" & -- код модели микросхемы hAA55
		"00000000001" &      -- код производителя (соответствует AMD)
		"1";                 -- единица по стандарту IEEE1149.1

	attribute REGISTER_ACCESS of SIMPLE_IC : entity is
		"DEVICE_ID	(IDCODE)," &
		"BYPASS	(BYPASS)," &	
		"BOUNDARY	(EXTEST, SAMPLE)";

	attribute BOUNDARY_LENGTH of SIMPLE_IC : entity is 8;
	attribute BOUNDARY_REGISTER of SIMPLE_IC : entity is
		"0 (BC_1, LED(0), output2, X)," &
		"1 (BC_1, LED(1), output2, X)," &
		"2 (BC_1, LED(2), output2, X)," &
		"3 (BC_1, LED(3), output2, X)," &
		"4 (BC_1, BTN(0), input,   X)," &
		"5 (BC_1, BTN(1), input,   X)," &
		"6 (BC_1, BTN(2), input,   X)," &
		"7 (BC_1, BTN(3), input,   X)" ;
end SIMPLE_IC;

На этом месте может возникнуть вопрос о правильности написания файла BSDL, проверке его синтаксиса, а также проверке соответствия файла самой микросхеме. То есть его верификации. В поисках аналогии взглянем, скажем, на IBIS — стандарт написания моделей выходных буферов цифровых микросхем. Группа, развивающая данный стандарт предлагает для свободного скачивания «Золотой парсер IBIS» — консольную утилиту, проверяющую синтаксис файла модели. В случае с JTAG такой утилиты нет. Зато имеется возможность онлайн-проверки на сайте компании «Intellitech», генеральным директором которой является Кристофер Кларк (C.J. Clark) — председатель группы JTAG. Ну как — «имеется»? Лично у меня по состоянию на 09.04.2022 при попытке загрузить туда файл BSDL происходит перенаправление на страницу ошибки. Онлайн-проверка файлов BSDL представлена также у компании «Asset Intertech». Проверив наш файл в этой системе мы получим следующий отчёт:

Job Status: Fail

Entity name: SIMPLE_IC
IEEE Std 1149.1-2001 (Version 2.0)
Error, Line 21, The number of LED pins does not match the port definition.
Error, Line 22, The number of BTN pins does not match the port definition.
Packaging option selected is PLCC20.
Error, Line 31, Port 'LED' has 4 missing pin mapping assignments.
Error, Line 31, Port 'BTN' has 4 missing pin mapping assignments.
Error, Line 42, Mandatory PRELOAD opcode was not specified.
Compilation failed due to errors.

Я бы поспорил со всеми указанными здесь ошибками, но если сделать так, как говорит система проверки синтаксиса: уменьшить количество линий в шинах «LED» и «BTN» до 4-х, а также добавить код для команды «PRELOAD», то результат будет такой:

Job Status: Pass

Entity name: SIMPLE_IC
IEEE Std 1149.1-2001 (Version 2.0)

Packaging option selected is PLCC20.
Inputs = 4
Outputs = 4
Bidirectionals = 0
Instruction Reg Length = 8
Boundary Reg Length = 8

BSDL compilation of 65 lines completed without errors.

В следующей статье мы напишем код на «Си» и «Verilog», который бы имитировал работу модуля JTAG микросхемы «SIMPLE_IC», описанием которого мы сейчас занимались. И параллельно, в деталях рассмотрим работу JTAG при выполнении различных инструкций.

Комментарии (5)


  1. lorc
    13.04.2022 20:03
    +1

    Спасибо, очень интересный цикл статей.

    Я в основном работаю с JTAG в режиме отладки MCU и больше разбираюсь в следующих уровнях - ARM Coresight, Debug Ports и всяком таком. Но все равно полезно знать что же там делает OpenOCD "под капотом" когда общается с процессором.

    Со стороны вот такого вот пользователя JTAG, я бы хотел дать совет: укажите где-то в начале статьи что JTAG не только для отладки кода. Что изначально его придумали как раз для boundary scan. Лично для меня это когда-то давно стало открытием.


  1. Flammmable Автор
    13.04.2022 20:22
    +3

    Спасибо, очень интересный цикл статей.

    Спасибо, что прочитали!

    укажите где-то в начале статьи что JTAG не только для отладки кода. Что изначально его придумали как раз для boundary scan.

    Субъективно, данный факт произносится настолько часто, что это порой надоедает ))) В данном же цикле хотелось бы сосредоточиться на вещах, которым, на мой взгляд не уделено достаточно внимания.

    В любом случае, во-первых, вы уже упомянули о том, что для чего делалось, во-вторых, в следующей статье назначение JTAG и так станет ясно из контекста.


  1. dec123
    13.04.2022 20:37
    +1

    класс, жду продолжения с прикладными примерами.


  1. San66
    14.04.2022 11:13
    +1

    Спасибо, очень полезный разбор. Как раз недавно писал на Python систему тестирования плат с использованием "urjtag", немного мучался с втаскиванием bsdl, пришлось их в json сначала пределать.


    1. Flammmable Автор
      14.04.2022 11:57
      +1

      Сами файлы BSDL - это та ещё штука! :)

      Как-то раз мне потребовался файл BSDL статической памяти в корпусе BGA одного известного производителя микросхем. В даташите на микросхему было написано:

      The Boundary Scan Descriptive Language (BSDL) file for this device is available by contacting your local XXX sales representative.

      ...что я собственно и сделал - обратился к представителю.

      Тот сказал, что центральный офис попросил 3 дня на упорядочивание архива. Я удивился "У них, что, архив файлов в бумажном виде, что им нужно 3 дня?" Спустя эти три дня ответ был следующий:

      Sorry that took so long. We could not find the files for the YYY_IC1.

      The ZZZ design team found a related device the YYY_IC2 with a similar BSDL file. There are differences in the addressing and /BW cells since the file is for a smaller device (128K vs 512K addresses).

      Perhaps you could modify this file. Our apps team does not have the capability to rewrite and check a modified file (we no longer have the necessary software).

      Это было мощно! )))