quartus I2C open-drain
Рассмотрим подключение пинов интерфейса к мастеру на примере ADS7128:
На изображении приведена цепь передачи данных с АЦП на приёмное устройство. При подаче логической единицы на базу транзистора Q в АЦП, цепь между Vpull_up и землей замыкается, значит для решающего устройства сигнал на пине GPOx будет восприниматься как логический 0. Однако, стоит изменить значение на базе транзистора Q на 0, как выход GPOx "подтянется" к питанию, что принимающим устройством воспримется как логическая единица.
Внутри СнК, к примеру, при работе с I2C в HPS ядре есть нюанс: двунаправленную шину данное ядро представляет как две отдельных линии, входную и выходную:
Однако физическое подключение к СнК выглядит как один двунаправленный порт:
Для сопряжения этих портов между собой необходимо воспользоваться блоком под названием ALT_IOBUF: он позволяет провести сопряжение между одним двунаправленным портом и двумя однонаправленными. Первое что приходит в голову — соединить эти порты со входами и выходами буфера, однако возникает проблема - каким сигналом осуществлять переключение между входом и выходом?
Ответ заключается в свойстве open-drain: нет необходимости форсировать состояние порта для единицы, достаточно либо "подключать" к земле, либо оставлять "висеть" в воздухе, что даёт возможность подтянуть линию к питанию. Итог использования данного буфера выглядит следующим образом:
В результате когда на SCL_out будет ноль, шина будет подтягиваться к земле (GND), при единице на шине — порт будет "отключаться" от земли, и внешнее питание будет подтягивать линию к единице.
При этом в коде для реализации разделения используют значение Z
, например:
VHDL:
IF( oe = '0') THEN
bidir <= "ZZZZZZZZ"
b <= bidir;
ELSE
bidir <= a;
b <= bidir;
END IF;
Verilog:
assign GPIO = SCL_out ? 1'b0 : 1'bz;
Ссылки на примеры: