Plain 168 18 апреля, 2020 Опубликовано 18 апреля, 2020 · Жалоба 14 часов назад, HardRock сказал: if (io_bits_count == 7) begin // - Copy IO buffer into RX buffer rx_buffer <= io_buffer; Это противоречит стандарту SPI — устройства могут соединяться последовательно, т.е. один сеанс обмена и один SS для всех, образуя один сдвиговый регистр произвольной разрядности и тактуемый одним общим SCLK, либо устройства могут соединяться параллельно, для индивидуальных сеансов обмена, т.е. SS у каждого свой собственный, SCLK по-прежнему общий, а все MISO и MOSI соединены параллельно, для этого MOSI и потребовалось третье состояние (но его может и не быть, т.е. не каждое устройство поддерживает шинный обмен) — в любом случае, всё, что двигалось сдвиговыми регистрами, переписывается в параллельные только по завершении сеанса, т.е. по снятии SS. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 14 18 апреля, 2020 Опубликовано 18 апреля, 2020 · Жалоба 16 часов назад, Flip-fl0p сказал: Где Вы в SPI нашли двунаправленные шины ? Трёхпроводной SPI. Там провод данных один, и он может переключаться со входа на выход прямо по ходу дела. Мастер, например, в четырёх битах выдал адрес регистра, в пятом -- чтение, а слейв должен начиная с шестого бита выдавать данные. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 18 апреля, 2020 Опубликовано 18 апреля, 2020 · Жалоба 1 минуту назад, andrew_b сказал: Трёхпроводной SPI. Там провод данных один, и он может переключаться со входа на выход прямо по ходу дела. Мастер, например, в четырёх битах выдал адрес регистра, в пятом -- чтение, а слейв должен начиная с шестого бита выдавать данные. Так я знаю, что существуют SPI с двунаправленными шинами . У меня сейчас такой в проекте применяется . Но всё-же такой spi - это слегка нестандатрная реализация. Я просто задавал наводящий вопрос Автору темы, чтобы он задумался над своей реализацией. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 18 апреля, 2020 Опубликовано 18 апреля, 2020 · Жалоба Приветствую! 32 minutes ago, Plain said: в любом случае, всё, что двигалось сдвиговыми регистрами, переписывается в параллельные только по завершении сеанса, т.е. по снятии SS. Это уж внутренне дело устройства - когда и с какой регулярностью принятые биты записывать - я могу потоком (в одном сеансе) гнать через SPI и 64 KB данных что-ж мне потом все эти биты разом переписывать из приемного регистра? Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 18 апреля, 2020 Опубликовано 18 апреля, 2020 · Жалоба Да это всё нестандартные вариации по мотивам SPI. Мне нужен SPI без последовательных соединений и т.п. Тоесть общий SCLK, а MOSI / MISO параллельно, SS у каждого свой. При этом протокол передачи хочу сделать похожий на SPI FLASH. Тоесть включаем SS, отправляем первый байт команды (например записать регистр), затем адер регистра и затем данные которые записываются. Аналогично с чтением. Поэтому нужно передавать несколько байт в рамках одной сессии (SS == 1). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 18 апреля, 2020 Опубликовано 18 апреля, 2020 (изменено) · Жалоба Подскажите пожалуйста, реализация условно "контроллера прерывания" сделана нормально? //! Interrupt module module Interrupt ( input wire in_clk, // - System clock input wire in_set, // - Set command input wire in_reset, // - Reset command output wire out_state // - Current state ); reg state; reg [1:0] setpulse; reg [1:0] resetpulse; assign out_state = state; always @(posedge in_clk) begin // - Update pulses setpulse <= { setpulse[0], in_set }; resetpulse <= { resetpulse[0], in_reset }; // - Detect set if (setpulse == 2'b01) state <= 1'b1; // - Detect reset if (resetpulse == 2'b01) state <= 1'b0; end endmodule Ожидаемое поведение: Выполняется на каждом системном клоке. Текущее состояние хранится в state. Когда на in_set приходит 1, а предыдущее значение там 0, то состояние переходит в 1. Аналогично с in_reset. Если нужно скинуть состояние в 0, то нужно на in_reset послать 1 когда там был 0. Результат смены текущего состояния out_state будет доступен во внешнем коде на следующем системном клоке. При использовании внешним кодом, прежде чем использовать например in_set, нужно убедиться что он выставлен в 0. Псевдокод always @(posedge clk) if (irq.in_set == 1) irq.in_set <= 0; ... irq.in_set <= 1; end ожидаемое поведение - хз. Как оно будет работать если так написать? Изменено 18 апреля, 2020 пользователем HardRock Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 18 апреля, 2020 Опубликовано 18 апреля, 2020 · Жалоба Приветствую! 27 minutes ago, HardRock said: ожидаемое поведение - хз. Как оно будет работать если так написать? Никак - первая строчка "if (irq.in_set == 0) irq.in_set <= 0; " бессмысленна - зачем ставить irq.in_set в 0 если уже она == 0 ? Может хотели так always @(posedge clk) irq.in_set <= 0; ... irq.in_set <= ~irq.in_set && (some_irq_request == 1); end Вы для начала разрисуйте стейт-диаграму вашей схемы - чтобы было понятно что и как управляет им (внешние сигналы) и как и куда переключается автомат (внутренние сигналы и состояния). Тогда многие вопросы станут значительно понятнее. Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 18 апреля, 2020 Опубликовано 18 апреля, 2020 (изменено) · Жалоба А почему она в нуле если в предыдущем цикле или в другом месте программы в неё записали 1? Wire от прерывания подключается к регистру в вызывающем коде (в псевдокоде не написал), соответственно кто сбросит регистр в ноль? Изменено 18 апреля, 2020 пользователем HardRock Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 18 апреля, 2020 Опубликовано 18 апреля, 2020 · Жалоба Приветствую! 27 minutes ago, HardRock said: А почему она в нуле если в предыдущем цикле или в другом месте программы в неё записали 1? В том то и дело - раз записали и irq.in_set станет ==1 - значит первая строчка никогда не выполнится. Так и будет стоять одинокой единицей P.S. А вот с исправленным условием if (irq.in_set == 1) irq.in_set <= 0; будет сбрасываться но тогда можно и просто написать irq.in_set <= 0; без всякого условия. Еще раз - тяжело оценивать форму облаков в тумане ночью. Делите ваш дизайн на законченные функциональные кусочки. Фиксируйте назначение, функционал и параметры входов/входов. И реализовывайте их как бы независимо. Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 18 апреля, 2020 Опубликовано 18 апреля, 2020 · Жалоба Ну тоесть предлагается в каждом клоке принудительно занулять регистр in_set, а дальше записывать в него 1 если нужно. Почему проверка в на 1 в начале клока не будет выполняться? Кстати, проверил отправку массива байт в самом модуле SPI - все отлично работает. Итого проблема в коммуникации модуля с внешним кодом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 18 апреля, 2020 Опубликовано 18 апреля, 2020 · Жалоба Приветствую! 9 minutes ago, HardRock said: Ну тоесть предлагается в каждом клоке принудительно занулять регистр in_set, а дальше записывать в него 1 если нужно. Почему проверка в на 1 в начале клока не будет выполняться? Потому что вначале вы написали if (irq.in_set == 0) irq.in_set <= 0; А вот исправленный вариант "if (irq.in_set == 1) irq.in_set <= 0;" и вариант "irq.in_set <= 0;" для синтеза (но не для симуляции) функционально одинаковы. Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 18 апреля, 2020 Опубликовано 18 апреля, 2020 · Жалоба А ну это опечатка была, я её поправил секунд через 30 :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 18 апреля, 2020 Опубликовано 18 апреля, 2020 (изменено) · Жалоба Разобрался почему не работает отправка нескольких байт. Дело действительно было в обработке прерываний, она занимает некоторое время, в течении которого системный клок успевает сделать несколько проходов. Изначально написал так: always @(posedge clk) begin // - Drop interrupt set requests spi_ivt_reset <= 0; // - IRQ_IO_START if (spi_ivt_status[0]) begin // - Reset byte index id <= 0; // - Reset interrupt spi_ivt_reset[0] <= 1'b1; end // - Wait IRQ_IO_BYTE if (spi_ivt_status[1]) begin // - Move to next byte id <= id + 1; debug <= debug == 0 ? 1 : 0; // - Reset interrupt spi_ivt_reset[1] <= 1'b1; end // - IRQ_IO_STOP if (spi_ivt_status[2]) begin // - Reset interrupt spi_ivt_reset[2] <= 1'b1; end end Осцилограмма во вложении. Желтым - состояние IRQ_IO_BYTE, синим состояние debug. Видно что дебаг успевает несколько раз сменить состояние, значит id плюсуется больше чем нужно. Если ввести буфер и ловить только передний фронт прерывания, то всё работает. always @(posedge clk) begin // - Drop interrupt set requests spi_ivt_reset <= 0; ivt_buffer <= { ivt_buffer[0], spi_ivt_status[1] }; // - IRQ_IO_START if (spi_ivt_status[0]) begin // - Reset byte index id <= 0; // - Reset interrupt spi_ivt_reset[0] <= 1'b1; end // - Wait IRQ_IO_BYTE if (ivt_buffer == 2'b01) begin // - Move to next byte id <= id + 1; debug <= debug == 0 ? 1 : 0; // - Reset interrupt spi_ivt_reset[1] <= 1'b1; end // - IRQ_IO_STOP if (spi_ivt_status[2]) begin // - Reset interrupt spi_ivt_reset[2] <= 1'b1; end end Вопрос: это нормальная практика - ловить передний фронт, или можно сделать более эффективно (без дополнительных регистров)? Как серьезные дядьки решают подобную задачу с прерываниями? PS: осцил ломаный до 100МГц, так что 50МГц тактовую показывает хорошо) Изменено 18 апреля, 2020 пользователем HardRock Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 18 апреля, 2020 Опубликовано 18 апреля, 2020 · Жалоба И всёравно немного залипает. Первый байт отправляется два раза. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 18 апреля, 2020 Опубликовано 18 апреля, 2020 · Жалоба Приветствую! 6 minutes ago, HardRock said: Вопрос: это нормальная практика - ловить передний фронт, или можно сделать более эффективно (без дополнительных регистров)? Как серьезные дядьки решают подобную задачу с прерываниями? Вы бы сначала объяснили серьезным дядькам какие бабло сигналы у вас есть и как вы хотите их обрабатывать. А то расклад на пальцах мутный какой-то и мы (серьезные дядьки) ни как в тему не вникнем Так что разложите все по полочкам - кто клиента обрабатывать должен - по какому событию - разовый наезд или постоянный прессинг - как сигналить что клиент дозрел? Удачи Rob. P.S. Словарь серьезных дядек клиент - прерывание разовый наезд - сигнал прерывания импульсом постоянный прессинг - сигнал прерывания уровнем клиент дозрел - подтверждение обработки прерывания Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться