Jump to content

    

EvgenyNik

Свой
  • Content Count

    592
  • Joined

  • Last visited

Everything posted by EvgenyNik


  1. Как выше подсказали - попробовать подгрузить выход драйвера. Встретился мне как-то (давно ещё) такой случай, когда вместо обычного шинного формирователя (АП5, АП6, 244, 245) поставили какой-то очень быстрый и на шине данных стали возникать ошибки. Оказалось всё просто - сигналы RD и WR приобрели излишнюю колебательность и как бы поступали дважды на управляющие входы.
  2. Слишком мощный выход драйвера может приводить к генерации колебаний на верхних гармониках.
  3. А Вы её для хранения и считывания констант хотите использовать? А то из текста можно подумать, что в качестве ОЗУ.
  4. Можно поинтересоваться - а с какой целью сие надобно? Если для того, чтобы поставить более мощную пин-ту-пин совместимую ПЛИС, то можно и новую плату собрать...
  5. Если допустить, что аналоги имеют иное значение конфигурационных ячеек, нежели исходные чипы, то логично запросить у производителя. Но компилятор то чей? Если забугорный, то он просто не сможет генерировать "дополнительные биты" и тогда всё стандартно. А гадать по начинке кристалла бессмысленно. В комнате 2 светильника по 5 плафонов - сколько клавиш у выключателя? :) К тому же, если не включать компрессию, то возможно, файл всегда создаётся максимального размера. Это надо проверить. Загрузочный автомат же может быть очень тупым - перекидал n бит и остановился.
  6. Можно. Но сначала надо решить вопрос с требуемой точностью. Результат на выходе фильтра будет зависеть не только от заполнения ШИМ, но и от амплитуды генератора, а та, в свою очередь, может зависеть не только от стабильности источника питания, но и от напряжения на конденсаторе фильтра (если выход слабый). Опять же, автор не указал - насколько быстро меняется заполнение во времени. Фильтр даст усреднённое значение, фактически, за несколько периодов. А вдруг, у него ШИМ генерирует сложный процесс и ему нужен каждый период.
  7. Приходится угадывать, конечно... Шина, случаем, не 5В? Сталкивался с похожей ситуацией, когда в результате ошибного подключения через пин попадало повышенной напряжение на локальное питание ПЛИС, отчего это питание задиралось и часть логических сигналов просто "проваливались" ниже уровня единицы, т.к. недотягивали. Есть ещё вариант - всплески напряжения в шине при коммутациях, которые теоретически могут приводить ко всякого рода защёлкиваниям.
  8. Ага. Потому что, имея ТЗ на коловорот и подключив всё своё представление о том как бывает плохо, когда что-то не учтено, изобретают дрель с вентильным движком :) А я с тем, что он говорит и не спорю. В конечном счёте все тонкости задачи известны только самому ТС. Не в полной мере ясно - что же, всё-таки, требуется: иметь максимально линейный перенос шкалы времени (тогда это больше отводит в сторону счётчиков, интерполяций, цифровых PLL и т.п., реализующих интегральные подстройки) или же чёткое квитирование прохождения определённых этапов (это ближе к фифо и около того). MegaVolt, а Вы можете написать - в каких пределах могут быть clk1 и clk2?
  9. Надеюсь, что будет понятно в продолжение о двух счётчиках, сама идея: Простой пример (clk1 < clk2) У нас бегущий секундомер натикивает за 5 секунд значение 7. Но мы то знаем (по синхросигналу), что должно быть 5. Делим 7/5=1.4. Происходит 1ый тик нашего неточного генератора, суммируем 0+1 = 1, это меньше чем 1.4, поэтому счёт вычисленных тиков пока 0. Происходит 2ой тик, суммируем: 1+1 = 2, что более, чем 1.4, поэтому вычитаем 2-1.4=0.6 и увеличиваем счётчик вычисленных тик 0+1 = 1 3ий: 0.6+1=1.6, 1.6-1.4=0.2, вычисленный 1+1=2 4ый: 0.2+1=1.2, вычисленный сохраняем 2 5ый: 1.2+1=2.2, 2.2-1.4=0.8, вычисленный 2+1=3 6ой: 0.8+1=1.8, 1.8-1.4=0.4, вычисленный 3+1=4 7ой: 0.4+1=1.4, 1.4-1.4=0 (сошлось!), вычисленный 4+1=5 (тоже получили что надо) Таким образом, мы на 7 тиках вычислили 5 требуемых с каким-то более-менее равномерным распределением. Другой случай (clk1 > clk2) Тоже самое, но сейчас наш секундомер отстаёт и за 5 секунд натикивает всего 3. Делим 3/5 = 0.6 1ый тик: 0+1 = 1, что больше чем 0.6, поэтому считаем 1, разница 1-0.6=0.4 2ой тик: 0.4+1 = 1.4, что более, чем 0.6, поэтому 1+1 = 2, разница 1.4-0.6=0.8, что снова больше, чем 0.6, значит считаем 2+1=3, остаток 0.8-0.6=0.2 3ий тик: 0.2+1 = 1.2, 3+1=4, 1.2-0.6=0.6, 4+1=5, 0.6-0.6=0. Снова сошлось: за 3 тика насчитали 5. --- Разница в том, что на ПЛИСке один из счётчиков (тот, на чьё значение надо делить) удобно сделать с фиксированным порогом счёта до числа равно двум в некой целой степени, чтобы делить простым сдвигом.
  10. А если так: 1. В домене clk2 создаём счётчик cnt2 (пусть от 0 до 127) 2. В домене clk1 создаём счётчик cnt1, разрядность которого позволяет с некоторым запасом не "кувыркнуться" через ноль, пока счетчик (cnt2) досчитает до 127 3. При достижении счётчиком cnt2 значения 127, сбрасываемся в 0 и формируем запрос в домен clk1 о передаче значения cnt1. 4. Получив запрос, счётчик cnt1 пересылает своё значение и сбрасывается в 0. 5. Таким образом, мы получаем какое количество тактов clk1 накапливается в счётчике cnt1 за время, пока счётчик cnt2 считает интервал в 128 тактов clk2. 6. Представив это значение в формате с фиксированной точкой мы получаем масштабный коэффициент, позволяющий вести эквивалентный счёт от тактов clk2 с представлением времени в домене clk1 в течении следующего интервала, пока не произойдёт обновление информации. Пример: cnt2 пробежал интервал в 128 тактов clk2, присланное значение cnt1 = 2309 clk1 Считаем 7 младших бит - дробной частью, тогда в десятичных получаем cnt1/cnt2 = 18,0390625. Теперь на каждый такт clk2 мы прибавляем к образе cnt1 значение 18,0390625: 18,0390625, 36,078125 и т.д. На следующем интервале cnt1 покажет число 2314, к примеру, и мы скорректируем наш масштабный коэффициент.
  11. Да, это запрос-ответ. Но и работало бы на такой же "скорости обмена". Чтобы пропускало меньше кода надо для счёта использовать не саму частоту тактирования, а поделенную на 2..4.
  12. FIFO не подойдёт, т.к. подразумевается разница частот, а значит буфер или переполнится или будет пустым. module cnt_copy ( input clk1, input clk2, output reg [7:0] cnt1, output reg [7:0] copy2 ); reg ready1 = 0; reg ready2 = 0; reg ready1_l1, ready1_l2; reg ready2_l1, ready2_l2; reg [7:0] cnt1_l; always @ (posedge clk1) begin ready2_l1 <= ready2; ready2_l2 <= ready2_l1; cnt1 <= cnt1 + 1; if (ready2_l2) begin if (~ready1) begin cnt1_l <= cnt1; ready1 <= 1'b1; end end else begin ready1 <= 1'b0; end end always @ (posedge clk2) begin ready1_l1 <= ready1; ready1_l2 <= ready1_l1; if (ready1_l2) begin if (ready2) begin copy2 <= cnt1_l; ready2 <= 1'b0; end end else begin ready2 <= 1'b1; end end endmodule Результат Указать таймбара стоит, как раз, на моменте, начиная с которого происходит передача значения "3". Далее тоже видно как передаются значения. С пропусками из-за синхронизации, но без искажения передаваемого значения.
  13. У MAX 10 есть на борту PLL. У него есть выход Locked. Даже если Вам "услуги" PLL не нужны, то можно завести клок на него только ради этого сигнала, чтобы обеспечить начальный сброс регистров в исходное положение стандартными средствами (подобие ресета). Не факт, что в дальнейшей поддержке не придётся в угоду фиттеру играться с настройками компилятора. Обнаружите, к примеру, что с галочкой Ignore initial проект весит меньше, обрадуетесь. И только когда-нибудь где-нибудь вылезет некорретная работа.
  14. Первая мысль, которая возникла - ограничивают мощность на выходе (потому и на более низком TTL ток можно развить выше). Но величина 16мА уже на 3.0В указывает, что дело не просто в ограничении мощности. Вероятно, дело в том, что последние поколения ПЛИС всё хуже и хуже справляются с перенапряжением (пусть и кратковременным) на выводах. И чтобы не создавать перенапряжения при коммутациях в области уровней, близких к критическим, ток там ограничивается. Как-то убил Циклон, вогнав в резонанс RLC-нагрузку на выходе 24МГц. На живом другом глянул - примерно 6В в амлитуде от выхода 3.3! Снизил ток в порядке эксперимента - помогло. А вообще, от силового применения выходных каскадов ПЛИС надо уходить. У MAXII/V тоже разброс был неслабый 3.33-5.66МГц. Для простых вещей хватает. Кстати, если есть некий внешний периодический низкочастотный сигнал, то при расположенности к искусственным трудностям :), можно заделать цифровую подстройку, потратив десятков 5-7 логических ячеек.
  15. Фактически, здесь написано: всегда при отрицательном фронте clk присваивать wramag=1, если stage равен 0 и, если иначе, то обнулять этот wramag. Так и делаем: 1. инвертируем clk (надо же по отрицательному фронту защёлкивать) и подаём на тактовый вход DFF 2. биты stage заводим на ИЛИ-НЕ и подаём на вход данных D 3. защёлкивам в DFF 4. снимаем результат с Q p.s. А зачем Вам манипуляции с OE и CS? Если используется один чип памяти и его порты работают через ПЛИС, то пусть по умолчанию всегда будет выбран и всегда в режиме выдачи данных с текущего адреса. Ему (чипу ОЗУ) всё равно, а Вам - экономия ресурсов на ПЛИСке.
  16. Создайте графический символ этому файлу и вставьте в свой проект. Может, ещё и не заработает. Чего зря рисовать то?
  17. Да. Разработать и производить можем сами. Просто хотелось для стартапа не совершать лишние телодвижения, т.к. и без этого работы полно.
  18. Попытка - не пытка. module sram #( parameter wdata = 8, parameter waddr = 10 ) ( input clk, input [waddr-1:0] ara_i, arb_i, awa_i, input [wdata-1:0] dw_i, output reg [wdata-1:0] da_or, db_or, inout [wdata-1:0] dram_io, output reg [waddr-1:0] aram_or, output oeram_o, output wram_o, output reg dataready_or ); assign oeram_o = 0; assign dram_io = (we_r ? rwram : {waddr{1'bz}}); assign wram_o = (we_r ? ~clk | wramag_r : 1'b1); reg [wdata-1:0] rwram; reg we_r; reg wramag_r; reg [1:0] stage_r; always @ (posedge clk) begin if (stage_r == 2'b10) stage_r <= 0; else stage_r <= stage_r + 1; case (stage_r) 2'b00: begin aram_or <= ara_i; we_r <= 0; dataready_or <= 0; end 2'b01: begin aram_or <= arb_i; da_or <= dram_io; rwram <= dw_i; end 2'b10: begin aram_or <= awa_i; db_or <= dram_io; we_r <= 1; dataready_or <= 1; end endcase end always @ (negedge clk) begin if (stage_r == 0) wramag_r <= 1; // это нужно, чтобы избавиться от глитча при возврате из режима записи (см. формирование wram_o) else wramag_r <= 0; end endmodule С времянками, конечно, получается вольно и лишь бы сама ОЗУшка успевала.
  19. Возможно. Потому что сейчас не понял я Покажу с помощью "наскальной живописи". Вот результат подачи ступеньки на режекторный фильтр. Вырезанная часть специально приподнята к средней линии. Фактически, если сложить то, что вырезано с тем, что осталось, то получится исходный сигнал (за вычетом округлений, т.к. в процессе фильтрации приходится разрядность увеличивать в "дробную сторону", а потом возвращать обратно округлением, и прочего по-мелочи навроде ограничения от выходов в минус и за пределы разрядности вверх), естественно, смещённый по времени. Однако, если задача поставлена - оставшиеся компоненты поместить в те позиции, где они были, то фронт получившегося отклика мы подтаскиваем к фронту исходного и вот теперь виден "хвост до собаки" :)
  20. Так-то всё верно, конечно, когда процесс происходит во времени. Но смотрите, вот какой пример. У нас есть некий массив с последовательностью, описывающей мгновенные значения многокомпонентного сигнала. Задача - вырезать какую-то частоту, сохранив для остальных одинаковое время групповой задержки. Создаём режекторный фильтр. Прогоняем через него массив и (а вот это важно!) складываем результат так, чтобы оставшиеся компоненты легли по тем же местам, где находились до режекции. Результат - из прежней последовательности удалена ненужная компонента, а остальное не тронуто. Что ожидаемо, но, всё равно, интересно - если из исходного массива поточечно вычесть новый, то получится вырезанная компонента. Причём, иногда таким "косвенным" способом её получается выделить даже лучше, чем полосовым фильтром. Понятно, что такое возможно только в отложенном времени. И даже когда делается налету, то только через буферизацию. Однако, если если в этот алгоритм подсунуть ступеньку, то будет то, о чём я писал ранее - реакция появится "ранее".
  21. Дык, Вам и пишут - как из обычного 100МГц ОЗУ сделать а-ля двухпортовое 50МГц ОЗУ. Только порты будут фактически на ПЛИСке.
  22. ТС в середине темы уточнил: А это значит, что примерно, всё-таки, известно. Более того, более-менее стандартны интервалы времени, на которые энергосистема может вываливаться на величину конкретного отклонения.
  23. Так же, как и при разложении в ряд Фурье, составляющие компоненты начинаются раньше, чем фронт раскладываемого сигнала. И только, будучи сложенными вместе, образуют его в первозданном виде. А если мы часть из них вырезаем, то, как раз, и получаем "хвост спереди". В современности, когда многие задачи решаются в цифре и в отложенном времени, это "раньше самого воздействия" уже не только возможно, но и даже используется. Сделав однажды подобный фильтр и демонстрируя заказчику его переходную функцию, тоже получил вопрос: как это так - ступеньки на входе ещё нет, а какие-то колебания уже есть? Предложил ему разложить прямоугольный импульс в ряд Фурье, исключить оттуда вырезаемые частоты и снова сложить... А поскольку вычислению с массивами неведомо прошлое и будущее, то там гром раньше молнии - явление вполне реальное.
  24. Ну тогда читать Вам надо по системе "запрос-ответ". Т.е. некий мастер выставляет запрос на чтение по определённому адресу, ваша ПЛИС "принимает" этот запрос и ожидает паузы между записями. Наступает пауза максимум через 4 такта, Вы читаете из ОЗУ и выставляете готовность - "забирай" :) Более того, учитывая, что читаете Вы на 10МГц, у Вас, как навскидку думается, есть все шансы - обработать "запрос на чтение" в этом же цикле чтения, не заставляя читающее устройство ждать.
  25. Но данные приходят по 8 бит, а ширина шины данных ОЗУ 16 бит, что даёт ему возможность накопить слово и записать его одним махом. А пока оно копится - прочитать 16 бит для выдачи.