Комментарии 10
Когда вы его подключите к AXI и начнете взаимодействовать из Linux, вы ведь нам расскажете, как написать свой драйвер?
Кажется базовый Verilog-кодинг стал одной из моих компетенций, но безусловно есть куда расти.
Например, перейти на SystemVerilog и использовать ='0; для инициализации ВСЕХ reg (в т.ч. led_driver.v и прочее).
Драйвер -- это, вообще говоря, либо простая железяка, которая "качает" другую железяку (скажем, драйвер двигателя), либо программа, реализующая логику управления чем-либо. Здесь, думается, корректней было бы говорить о контроллере семисегментника и т.д., а не о драйвере. Но это так, придирки :)
необходимо будет придумать SPI-автомат
А чего его придумывать? Обычный сдвиговый регистр + клоки + CS.
Здравствуйте.
У меня получилось перенести этот дизайн в VIVADO под Kintex XC7K325T.
Я решил это сделать в графическом виде.
В процессе возникли сложности с синтезом. Никак не хотели синтезироваться конструкции с тремя состояниями из прошлой статьи.
assign scl_io = (scl_r) ? 1'bz : 1'b0;
У меня от такой записи синтезировались просто OBUF ну и конечно же обе линии (SCL, SDA) "лежали за "земле". Кстати если заменить "z" значение в этом мультиплексоре на "1", то осциллограмма получалась верная, но OBUF не работают на вход.
Мной были использованы OBUFT (https://docs.amd.com/r/en-US/ug953-vivado-7series-libraries/OBUFT) для SCL и IOBUF (https://docs.amd.com/r/en-US/ug953-vivado-7series-libraries/IOBUF) для SDA.
В коде это выглядит вот так:
// assign scl_io = (~scl_r) ? 1'b0 : 1'bz; // избавляемся от мультиплексора
OBUFT #( // включаем OUTPUT в библиотечный элемент
.DRIVE(12), // Specify the output drive strength
.IOSTANDARD("DEFAULT"), // Specify the output I/O standard
.SLEW("SLOW") // Specify the output slew rate
) OBUFT_inst_scl (
.O(scl_io), // Buffer output (connect directly to top-level port)
.I(1'b0), // Buffer input
.T(scl_r) // 3-state enable input
);
Теперь в SCHEMATIC можно наблюдать правильный выход после синтеза:
С SDA чуть-чуть посложнее. IOBUF был включен в TOP-LEVEL файле. Для это из I2C_bit_controller потребовать вывести сигнал наружу:
//---------------------------------------------------
assign T = into_w || sda_r; // здесь Т - это OUTPUT
//---------------------------------------------------
Теперь в TOP-LEVEL файле подключаем библиотечный элемент:
wire T; // провод для design_wrapper
wire sda_w; // провод sda, по нему пойдут даннные из SLAVE в MASTER через IOBUF
IOBUF IOBUF_inst_sda (
.O(sda_w), // Buffer output
.IO(sda_io), // Buffer inout port (connect directly to top-level port) // sda_io
.I(), // Buffer input
.T(T) // 3-state enable input, high=input, low=output // (into_w || sda_r)
);
В design_wrapper включаем правильные сигналы:
...
.scl_io_0(scl_io),
.sda_io_0(sda_w), // sda_io
...
Теперь это будет работать на реальном железе. На моей кастомной плате нет семисегментников, поэтому для вывода данных была использована двухпортовая BRAM память. Один порт в Microblaze, а второй управляется кастомным контроллером из прошлых статей автора. Так для отображения всех данных я буду использовать терминал, данные в который поступают из софт-процессора MICROBLAZE. По линии I2С на этой плате управляется PLL LMK03318 (https://qeeniu.net/product/LMK03318#all). В cnt_0_data (по адресу 0xC000000C) отображается номер регистра, в cnt_1_data (по адресу 0xC0000010) данные, которые мы хотим записать по i2c линии в микросхему, а в cnt_2_data (по адресу 0xC0000014) считанные данные.
После включения питания и сброса (по кнопке RESET) адрес регистра устанавливается в 0xA, а данные, которые необходимо записать в 0xDE.
Нажимаю кнопку чтения.
В регистр записалось значение 0x0A, что по даташиту соответствует адресу микросхемы по-умолчанию.
Установим адрес 0xC
и запишем по этому адресу значение 0xDE в микросхему. Это будет соответствовать отключению функции AUTOSTART LMK03318.
Делаю сброс (кнопкой RESET) и считываю регистры в приложении для Microblaze:
А потом опять 0xDF
Summary. Пользуясь моментом хочу сказать спасибо автору этих статей, я думаю что благодаря Вам проектирование под плис и программирование становится доступным каждому кто захочет в этом разобраться. Комментарий получился объемным, но очень поверхностным. Если у кого-то будут вопросы - не стесняйтесь писать, я постараюсь ответить.
Создаем I2C Master Controller на Verilog. Проверим работу на реальном железе