Flip-fl0p 4 16 апреля, 2020 Опубликовано 16 апреля, 2020 · Жалоба 2 минуты назад, RobFPGA сказал: Приветствую! А это уже другие премудрости - построение цифровой схемы Когда вы заводите внешние асинхронные к клоку clk сигналы (SS, SCLK) в синхронную схему обязательно их надо пропустить через синхронизатора (2-3 D триггера подряд) чтобы убрать эффект метастабильности. В железе в отличии от программы - сигнал физически имеет конечную скорость и не всегда успевает долететь до середины Днепра... до разных частей схемы вовремя. И когда вы пишете ... if (SS==1) ... это не значит что проверка идет физически в одном месте - реально может быть десятки/сотни физически разных мест где это строчка реализуется в железе. Поэтому пропуская через синхронизатор вы гарантируте что вся ваша синхронная схема будет получать чистый и один и тот же сигнал. Для этого кстати служать и timing constrain которые вы тоже должны задавать для компиляции в конкретную FPGA. Но это уже к Verilog отношение имеет опосредсвенно. Удачи! Rob. Немножечко дополню. Физически сигнал ещё имеет время нарастания фронта. И если сигнал медленный а ПЛИС быстрая, то такой медленный сигнал может восприниматься схемой не всегда однозначно. А если учесть что линии могут быть отражения, и внешние наводки, о внутри ПЛИС одиночный сигнал от внешнего устройства может быть интерпретирован как несколько сигналов. Почти как дребезг от кнопки. Крайне желательно входной сигнал пропустить после синхронизаторов через небольшой фильтр дребезга. Во всяком случае у меня всегда все входные сигналы от медленных интерфейсов фильтруются от дребезга. И проблем у меня с ними не было. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Джеймс 3 16 апреля, 2020 Опубликовано 16 апреля, 2020 · Жалоба 3 hours ago, HardRock said: Если правильно понимаю, самый "правильный" способ - это тактироваться от системного клока и вручную искать фронты SPI сигнала? Но при этом сложность реализации сильно возрастает... Да. Именно. Но зато все будет работать. 2 hours ago, HardRock said: Не знал что можно писать posedge|negedge, в описании языка таких конструкций не находил, Ээх, нельзя так писать. Ув. RobFPGA другое имел в виду, он некое обобщенное описание синтаксиса приводил.. Совсем без стандарта вам не обойтись. Советую изучить вот этот документ: 1364.1-2002 - IEEE Standard for Verilog Register Transferhttp://www.iuma.ulpgc.es/~nunez/clases-FdC/verilog/Verilog-IEEE-1364.pdf Там на страницах 9-10 как раз найдете, во что превращается конструкция вида always @ (posedge clock or posedge set) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 16 апреля, 2020 Опубликовано 16 апреля, 2020 · Жалоба Приветствую! 4 minutes ago, Джеймс said: 3 hours ago, HardRock said: Если правильно понимаю, самый "правильный" способ - это тактироваться от системного клока и вручную искать фронты SPI сигнала? Но при этом сложность реализации сильно возрастает... Да. Нет... Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Джеймс 3 16 апреля, 2020 Опубликовано 16 апреля, 2020 · Жалоба 1 minute ago, RobFPGA said: Нет... Удачи! Rob. Флейма не будет ; ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 16 апреля, 2020 Опубликовано 16 апреля, 2020 · Жалоба Приветствую! 1 minute ago, Джеймс said: Флейма не будет ; ) Какого флейма? - я же сказал - "Нет" ... сложность не возрастет. Даже проще будет! Это же всем ясно Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Джеймс 3 16 апреля, 2020 Опубликовано 16 апреля, 2020 · Жалоба Just now, RobFPGA said: Приветствую! Какого флейма? - я же сказал - "Нет" ... сложность не возрастет. Даже проще будет! Это же всем ясно Удачи! Rob. А, ясно : ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Jackov 1 16 апреля, 2020 Опубликовано 16 апреля, 2020 · Жалоба 8 часов назад, HardRock сказал: Всем привет. Начал изучение FPGA, есть ряд вопросов. Могу посоветовать посмотреть эти лекции по Верилогу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 16 апреля, 2020 Опубликовано 16 апреля, 2020 · Жалоба На тему дебаунса, сделал на автомате с дебаунсом. Перестало работать. Посмотрел что происходит, получилось так (на фото). Первый канал это клок SPI, второй - тактирование циклона. Получается что дебаунс сюда не подходит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Plain 168 17 апреля, 2020 Опубликовано 17 апреля, 2020 · Жалоба 13 часов назад, HardRock сказал: самый "правильный" способ - это тактироваться от системного клока и вручную искать фронты SPI сигнала? Но при этом сложность реализации сильно возрастает... Не ясно, что по-вашему "сложность", но выглядит оно примерно так: assign MISO = (ssbuf[1]) ? spireg[7] : 1'bz; always @(posedge clk) begin sclkbuf <= { sclkbuf[0], SCLK }; mosibuf <= { mosibuf[0], MOSI }; ssbuf <= { ssbuf[0], SS }; if (ssbuf == 2'b01) begin spireg <= spitx; end if (ssbuf == 2'b10) begin spirx <= spireg; end if (sclkbuf == 2'b01) begin spireg <= { spireg[6:0], mosibuf[1] }; end end Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_K 0 17 апреля, 2020 Опубликовано 17 апреля, 2020 · Жалоба 14 hours ago, HardRock said: always @(SS, SCLK) begin Извините, не удержался. 10 hours ago, HardRock said: На тему дебаунса, сделал на автомате с дебаунсом. При чём тут debounce? Вам уже несколько раз сказали - посмотрите стандарты и примеры как "отрабатывается" написанный код. Элементарно посмотрите во что синтезируется Ваш первый модуль. Потом нарисуйте схему (да ручкой на бумажке) как Вы хотите, чтобы работал Ваш слейв. А потом попытайтесь описать то что нарисовано с помощью Verilog'а. Вот когда код синтезируется в то что нарисовано - тогда придёт понимание происходящего. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 17 апреля, 2020 Опубликовано 17 апреля, 2020 · Жалоба 10 часов назад, HardRock сказал: На тему дебаунса, сделал на автомате с дебаунсом. Перестало работать. Посмотрел что происходит, получилось так (на фото). Первый канал это клок SPI, второй - тактирование циклона. Получается что дебаунс сюда не подходит. А вот нельзя Вам по утрам в зеркало смотреться. А то ведь под горячую руку побьете зеркало. А оно не виновато, что "дебаунс сюда не подходит"... Но, с другой стороны, эта переписка несколько оживила форум. И еще. Если не хотите искать учебники и стандарты, то и хрен с ними. Есть альтернативный и незатратный вариант. Надо найти щуку и тогда "все и сразу и само". Наверняка сейчас в гипермаркетах можно купить, главное чтобы была живая и говорящая... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 17 апреля, 2020 Опубликовано 17 апреля, 2020 · Жалоба Вобщем пока сделал так: module SPISlave( input wire clk, /* --- SPI Connection --- */ inout wire SS, input wire SCLK, input wire MOSI, output wire MISO, /* --- RxTx Buffers --- */ output reg[7:0] rx_buffer = 8'b00000000, input wire[7:0] tx_buffer, output reg io_next_byte ); //! Number of bits since start of session reg [4:0] io_bits_count; //! FSM State reg [4:0] fsm; integer debounce; parameter WAIT_SS = 0; parameter WAIT_SCLK = 1; parameter READ_BIT = 2; parameter WRITE_BIT = 3; parameter NEXT_BIT = 4; initial begin io_bits_count <= 0; fsm <= WAIT_SS; debounce <= 0; end always @(posedge clk) begin case (fsm) // - Wait for SS WAIT_SS: begin io_bits_count <= 0; debounce <= 0; if (SS == 1) fsm <= WAIT_SCLK; end // - Wait for SCLK goes HIGH WAIT_SCLK: begin if (SS == 1) begin if (SCLK == 1) begin fsm <= READ_BIT; io_next_byte <= 0; end end else begin fsm <= WAIT_SS; end end // - Ensure SCLK is high and read bit READ_BIT: begin if (SS == 1 && SCLK == 1) begin rx_buffer <= { rx_buffer[6:0], MOSI }; fsm <= WRITE_BIT; end else begin fsm <= WAIT_SS; end end // - Write next bit WRITE_BIT: begin if (SS == 1 && SCLK == 1) begin fsm <= NEXT_BIT; end else begin fsm <= WAIT_SS; end end // - Wait LO NEXT_BIT: begin if (SS == 1) begin if (SCLK == 0) begin if (debounce < 1) debounce <= debounce + 1; else begin io_bits_count <= io_bits_count + 1'b1; if (io_bits_count == 8) begin io_bits_count <= 0; io_next_byte <= 1; end debounce <= 0; fsm <= WAIT_SCLK; end end end else begin fsm <= WAIT_SS; end end endcase end assign MISO = tx_buffer[7 - io_bits_count]; endmodule Оставил тест на ночь в железе пинать 1 байт с небольшой задержкой и рестартом цикла + с ловушками что если циклон или микроконтроллер примут битые данные то тест останавливается. Передалось на данный момент чуть больше 6.5 мегабайт. Рабоает :) При произвольных перезагрузках железок или выдергивании проводов тоже работает. Заметил на осцилографе что сбой происходил на заднем фронте SCLK (циклон почему-то начинал думать что SCLK уже LOW, хотя ещё HIGH) , добавил задержку в 1 такт при ожидании SCLK в ноль (состояние NEXT_BIT), стало работать стабильно. Но мне это кажется каким-то костылём под конкретную скорость работы порта и подключения (МК и циклон соединены через преобразователь уровней 3.3 - 5). Наверно при другой ситуации может сбоить если нарастание / спад будет отличаться. Как вообще в таких случаях стоит синхронизировать чтобы работало в общем случае? Выход с AVR'ки на осцилографе выглядит точнее, при том что забираю его уже с циклона (дублирую сигналы на отдельные выводы) 1 час назад, Plain сказал: Не ясно, что по-вашему "сложность", но выглядит оно примерно так: Интересный вариант) Попробую. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 17 апреля, 2020 Опубликовано 17 апреля, 2020 · Жалоба 1 час назад, iosifk сказал: Есть альтернативный и незатратный вариант. Надо найти щуку и тогда "все и сразу и само". Наверняка сейчас в гипермаркетах можно купить, главное чтобы была живая и говорящая... К щуке придётся ещё искать пиво живое, а с ним сейчас сложно, карантин, да и совсем перестал употреблять спиртное уже несколько лет как, теперь только в бачок омывайки заливаю вкуснейший этиловый спирт))) Так что придётся вникать во все нюансы по мере необходимости. Мне кстати вариант "жарьте, а масло потом поднесут", как вы говорили, в изучении больше нравится, быстрее практический опыт идёт чем "скучная теория". Благо требования к надёжности сильно ниже и это не промышленная разработка. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 17 апреля, 2020 Опубликовано 17 апреля, 2020 (изменено) · Жалоба 4 часа назад, Plain сказал: assign MISO = (ssbuf[1]) ? spireg[7] : 1'bz; always @(posedge clk) begin sclkbuf <= { sclkbuf[0], SCLK }; mosibuf <= { mosibuf[0], MOSI }; ssbuf <= { ssbuf[0], SS }; if (ssbuf == 2'b01) begin spireg <= spitx; end if (ssbuf == 2'b10) begin spirx <= spireg; end if (sclkbuf == 2'b01) begin spireg <= { spireg[6:0], mosibuf[1] }; end end Можете пожалуйста прокомментировать как это работает? А оно реально работает и стабильно. sclkbuf и ssbuf всё понятно - это детект фронтов. Не понятно что происходит со spireg, он используется и для приема и для передачи, при этом вроде как данные не смешиваются. Если правильно понял то в spireg при переходе SS из 0 в 1 записывается значение TX буфера, затем это значение с каждым тактом SPI клока выталкивается вправо (к старшим битам) в MISO, а на место освободившихся бит записывается значение из MOSI. Когда SS переходит в ноль, значение из spireg записывается в RX буфер. Изменено 17 апреля, 2020 пользователем HardRock Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yes 5 17 апреля, 2020 Опубликовано 17 апреля, 2020 · Жалоба а почему никто не советует какой-нибудь HLS - у альтеры же есть своя подобная штука? положим я олдфаг и HLS-ом этим никогда не пользовался. но его же не зря так форсят (и усердно и уже давно) ксайлинс с альтерой - есть кто-нибудь в конфе кто пользовался? насколько я понимаю, это как раз и нужно для программиста, чтобы не вникать во всю эту трахомудь с "дизайном цифровых схем". по-крайней мере на каком-то начальном этапе. ??? 1 hour ago, HardRock said: Если правильно понял то в spireg при переходе SS из 0 в 1 записывается значение TX буфера, затем это значение с каждым тактом SPI клока выталкивается вправо (к старшим битам) в MISO, а на место освободившихся бит записывается значение из MOSI. Когда SS переходит в ноль, значение из spireg записывается в RX буфер. это происходит одновременно, не последовательно. собственно поэтому и HDL, а не Питон, например Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться