justontime 0 24 января, 2015 Опубликовано 24 января, 2015 · Жалоба Приведенный пример построения и есть работа от одного тактового сигнала. Проблема в том, что я, из-за отсутствия формального образования в этой области, активно изобретаю велосипеды. Причем с рулем сзади и треугольными колесами :) Например, я не понимаю, как в Вашем примере мне просто определить, что произошло изменение NewCode с 0 до 1 (именно из-за этого у меня и был rising_edge(NewCode))... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
justontime 0 24 января, 2015 Опубликовано 24 января, 2015 · Жалоба Переписал, вроде стало понятнее и проще: process (rst, clk) begin if rst = '1' then BreakCode <= '0'; kbdIRQ <= '0'; else if rising_edge(clk) then if NewCode = '1' then if ScanCodeT = x"F0" then BreakCode <= '1'; else XTcode <= BreakCode & ScanCodeT(6 downto 0); BreakCode <= '0'; kbdIRQ <= '1'; end if; else kbdIRQ <= '0'; end if; end if; end if; end process; И даже почти заработало - если убрать из else строчку BreakCode <= '0' , то один раз отрабатывает правильно. Потом, естественно, из-за застрявшего в 1 сигнала BreakCode уже работает неправильно. А вот если вернуть строчку обнуления BreakCode, то старший бит получившегося XTcode всегда равен 0. Я считал, что все изменения внутри такой конструкции произойдут по окончании процесса, но явно ошибался - такое впечатление, что в присвоении XTcode <= BreakCode & ScanCodeT(6 downto 0) всегда используется уже сброшенный в 0 сигнал BreakCode. Я вообще правильно размышляю ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 24 января, 2015 Опубликовано 24 января, 2015 · Жалоба надо фундоментально. вы понимаете разницу между if rst = '1' then ... elseif rising_edge(clk) .. endif и if rising_edge(clk) then if(rst = '1') then .... elseif .... endif Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
justontime 0 24 января, 2015 Опубликовано 24 января, 2015 · Жалоба надо фундоментально. вы понимаете разницу между ... Очевидно, я действительно не понимаю что-то очень фундаментальное... На мой взгляд, разница в приведенных Вами примерах только в том, что там асинхронный и синхронные сбросы, или же там есть еще что-то существенное ? Я переписал сейчас: process (rst, clk) begin if rising_edge(clk) then if rst = '1' then BreakCode <= '0'; kbdIRQ <= '0'; elsif NewCode = '1' then if ScanCodeT = x"F0" then BreakCode <= '1'; else XTcode <= BreakCode & ScanCodeT(6 downto 0); BreakCode <= '0'; kbdIRQ <= '1'; end if; else kbdIRQ <= '0'; end if; end if; end process; но поведение, похоже, вообще не изменилось... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 24 января, 2015 Опубликовано 24 января, 2015 · Жалоба асинхронные схемы изначально более сложны в анализе и проектировке. А так же тяжелее синтезируются. Самое удобное - это выбрать одну частоту и все сделать на ней синхронно, есть много способов как синхронизировать внешние сигналы, и если нет особой нужды нечего заниматься асинхронщиной, Вам принципиально чтобы сброс был по фронту ресета, а не по уровню? Задержка в 1 клок на сбросе погоду сделает? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
justontime 0 24 января, 2015 Опубликовано 24 января, 2015 · Жалоба Вам принципиально чтобы сброс был по фронту ресета, а не по уровню? Задержка в 1 клок на сбросе погоду сделает? Да мне вообще все-равно - в принципе, там сброс даже не совсем обязательный (по идее, вроде clk сам собой приведет схему в нужное состояние). Главное, я не могу понять, почему (независимо от типа сброса и т.д.) у меня этот долбанный BreakCode исчезает... :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 24 января, 2015 Опубликовано 24 января, 2015 · Жалоба едем дальше if rst = '1' then BreakCode <= '0'; kbdIRQ <= '0'; elsif NewCode = '1' then почему состоянию ресета противопоставляется состояние с NewCode ='1' ? кроме смысла хорошо бы еще читаемость кода повысить. отображайте суть if rising_edge(clk) then if rst = '1' then BreakCode <= '0'; kbdIRQ <= '0'; else if NewCode = '0' then kbdIRQ <= '0'; endif if NewCode = '1' then if ScanCodeT = x"F0" then BreakCode <= '1'; else XTcode <= BreakCode & ScanCodeT(6 downto 0); BreakCode <= '0'; kbdIRQ <= '1'; endif endif endif такое поведение вы хотели описать? что мы видим если на фронт клока NewCode = '1 и ScanCodeT = x"F0" то BreakCode <= '1'; если на фронт клока NewCode = '1 и ScanCodeT != x"F0" то XTcode <= BreakCode & ScanCodeT(6 downto 0); BreakCode <= '0'; kbdIRQ <= '1'; казалось бы все очевидно, и теперь я задам вопрос, а как меняется переменная NewCode и ScanCodeT? потому что на самом деле ваша схема выглядит так допустим NewCode = '1 if ScanCodeT1 = x"F0" then BreakCode <= '1'; endif if ScanCodeT2 != x"F0" (простите не помню как будет не равно в ВХДЛ) XTcode <= BreakCode & ScanCodeT(6 downto 0); endif if ScanCodeT3 != x"F0" (простите не помню как будет не равно в ВХДЛ) BreakCode <= '0'; endif if ScanCodeT4 != x"F0" (простите не помню как будет не равно в ВХДЛ) kbdIRQ <= '1'; endif то есть если у вас что-то находиться под одним IF это не значит что оно все выполниться или не выполниться одновременно, в синтезе каждое условие будет разведено относительно входных сигналов и фактически будет одно под своим IF и теперь самое интересное я специально написал ScanCodeT1,ScanCodeT2,ScanCodeT3,ScanCodeT4, потому что части схемы реализующие каждый IF могут попасть в разные части кристалла в железе и сигнал ScanCodeT4 в целом не равен ScanCodeT3, ScanCodeT2, ScanCodeT1, они все друг с другом не равны потому что к моменту фронта клока в одной части он дошел и стал 1, в другой еще в пути и там еще 0 и все ваши IF развалятся.... половина выполниться, другая нет вам надо ваш сигнал синхронизовать с клоком, чтобы к фронту клока во всех частях схемы он был единым есть стандартный метод if rising_edge(clk) then Signal2 = Signal1; Signal1 = InputSignal; endif и вот тогда если InputSignal может измениться в любой момент, то Signal2 будет меняться точно по фронту, и доходить своим значением до всех частей схемы к следующему фронту одинаково... Есть некоторые сложности с шинами, то есть если входной сигнал многобитовый, для такого сигнала хорошо бы иметь 1 разрешающий проводок, который покажет что все входные биты заняли нужное значение, а то может так оказаться что поймаете момент переключения и получиться что половина проводков защелкнулось в новом состоянии, а другая в старом. Или же защелкивайте сигнал по 2 раза, и проверяйте результат, если 1 и 2 раз совпали. значит защелкнули верное значение и отправляйте его на следующий триггер, а потом уже в общую схему. И тогда все заработает как надо зачем защелкивать 2 раза? есть еще такая штука метастабильность, то есть триггер защелкивает 1 или 0, но есть некое средние положение входного сигнала когда триггер повисает и некоторое время думает что выдать, и потом сваливается в 1 или в 0. Если щелкаете ассинхронные сигналы, у вас всегда есть вероятность что в момент переключения будет фронт клока, и вы поймаете это средние положение, но оно не повесит всю схему, оно повесит 1 триггер, а второй будет выдавать прошлое значение. Повисшее состояние длиться не вечно и большая вероятность что к след фронту входной триггер уже определиться что выдавать 0 или 1, и дальше все поедет как надо. Так что есть золотое правило все асинхронные входные сигналы пропустите через 2 триггера на входе, чтобы получить хороший, защищенный от метастабильности сигнал и одинаковый во всех частях схемы... П.С. Я давно не пишу на VHDL, но надеюсь смысл конструкций понятен. И я вижу внизу iosifk появился:) послушайте его, ему есть что сказать начинающим:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
justontime 0 24 января, 2015 Опубликовано 24 января, 2015 · Жалоба Во первых, огромное спасибо за разъяснения ! Даже хотя пока мне не удалось решить проблему, я реально благодарен всем, тратящим свое время на подобные ответы ! Если же ближе к теме, то вроде все слова по отдельности понял, а вот вместе смысл слегка убегает... В каком месте и какой сигнал нужно синхронизировать ? Сначала я подумал, что у меня ScanCodeT действительно не успевает добежать до всех мест (в принципе, и ScanCodeT, и NewCode формируются по восходящему clk), поэтому я задержал NewCode на пол-clk, чтобы ScanCodeT к этому моменту гарантированно устаканился. К сожалению, это не поменяло вообще ничего. Далее перечитал Ваше сообщение и пришел к выводу, что Вы говорите о чем-то другом, но пока понять не могу... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 24 января, 2015 Опубликовано 24 января, 2015 · Жалоба если у вас сигналы ScanCodeT и NewCode формируются по восходящему фронту clk то при задании стандартных констраинов на клок вида Period = N, синтезатор следит чтобы эти сигналы оказывались во всех местах куда они должны дойти к следующему восходящему фронту клока. Если же вы используете формируемый по восходящему фронту сигнал, по падающему фронту в надежде что у вас будет клок и еще половинка, то на самом деле у вас будет всего пол клока. Но синтезатор без дополнительных констраинов на установку и удержание сигнала за этим моментом не следит. И если они пишет что все констраины выполнились, то это не значит что сигнал начав свой подъем по восходящему фронту, в ближайший нисходящий фронт окажется везде в поднятом состоянии... Или я что-то не так понял про задержку на полтакта? В общем не стоит работать по разным фронтам клока, если это не требует особенно чем-то извне. Потому что в этом случае вы теряете проверки синтезатора метастабильность про которую я писал - это для внешних асинхронных сигналов, или сигналов формируемых по разным клокам, если у вас один единый клок на всю схему, то это вас пока не касается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
justontime 0 24 января, 2015 Опубликовано 24 января, 2015 · Жалоба метастабильность про которую я писал - это для внешних асинхронных сигналов, или сигналов формируемых по разным клокам, если у вас один единый клок на всю схему, то это вас пока не касается. Так какого фига оно не работает ??? :) Вроде все перепробовал, что сам смог придумать, и что посоветовали... Последний вариант: process (rst, clk) begin if rising_edge(clk) then if rst = '1' then BreakCode <= '0'; kbdIRQ <= '0'; else if NewCode = '0' then kbdIRQ <= '0'; end if; if NewCode = '1' then if ScanCodeT = x"F0" then BreakCode <= '1'; else XTcode <= BreakCode & ScanCodeT(6 downto 0); BreakCode <= '0'; kbdIRQ <= '1'; end if; end if; end if; end if; end process; Причем во всех вариантах (не)работоспособность проявлялась совершенно идентично... Мне почему-то кажется, что ларчик должен открываться очень просто - что-то на поверхности... Так какого фига оно не работает ??? :) ... Мне почему-то кажется, что ларчик должен открываться очень просто - что-то на поверхности... Действительно, все оказалось крайне просто... Схема подразумевает, что сигнал NewCode находится в активном состоянии один цикл клока, и у меня есть отдельный процесс, обеспечивающий это. Так вот, этот процесс не работал :) Как только исправил его, все завелось ! В любом случае, еще раз всем спасибо - все-равно узнал новые для себя вещи, да процесс сейчас намного более красивый, чем в моем первоначальном варианте. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться