Перейти к содержанию
    

Странные вопросы по VHDL

Приведенный пример построения и есть работа от одного тактового сигнала.

 

Проблема в том, что я, из-за отсутствия формального образования в этой области, активно изобретаю велосипеды. Причем с рулем сзади и треугольными колесами :)

 

Например, я не понимаю, как в Вашем примере мне просто определить, что произошло изменение NewCode с 0 до 1 (именно из-за этого у меня и был rising_edge(NewCode))...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Переписал, вроде стало понятнее и проще:

 

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.

 

Я вообще правильно размышляю ?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

надо фундоментально.

 

вы понимаете разницу между

 

if rst = '1' then
...
elseif rising_edge(clk)
..
endif

 

и

 

if rising_edge(clk) then
  if(rst = '1') then
  .... 

  elseif 
  ....

endif

 

 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

надо фундоментально.

 

вы понимаете разницу между

 

...

 

Очевидно, я действительно не понимаю что-то очень фундаментальное... На мой взгляд, разница в приведенных Вами примерах только в том, что там асинхронный и синхронные сбросы, или же там есть еще что-то существенное ?

 

Я переписал сейчас:

 

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;

 

но поведение, похоже, вообще не изменилось...

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

асинхронные схемы изначально более сложны в анализе и проектировке. А так же тяжелее синтезируются.

Самое удобное - это выбрать одну частоту и все сделать на ней синхронно, есть много способов как синхронизировать внешние сигналы, и если нет особой нужды нечего заниматься асинхронщиной,

 

Вам принципиально чтобы сброс был по фронту ресета, а не по уровню? Задержка в 1 клок на сбросе погоду сделает?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вам принципиально чтобы сброс был по фронту ресета, а не по уровню? Задержка в 1 клок на сбросе погоду сделает?

 

Да мне вообще все-равно - в принципе, там сброс даже не совсем обязательный (по идее, вроде clk сам собой приведет схему в нужное состояние).

 

Главное, я не могу понять, почему (независимо от типа сброса и т.д.) у меня этот долбанный BreakCode исчезает... :(

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

едем дальше

 

 

          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 появился:) послушайте его, ему есть что сказать начинающим:)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Во первых, огромное спасибо за разъяснения ! Даже хотя пока мне не удалось решить проблему, я реально благодарен всем, тратящим свое время на подобные ответы !

 

Если же ближе к теме, то вроде все слова по отдельности понял, а вот вместе смысл слегка убегает... В каком месте и какой сигнал нужно синхронизировать ? Сначала я подумал, что у меня ScanCodeT действительно не успевает добежать до всех мест (в принципе, и ScanCodeT, и NewCode формируются по восходящему clk), поэтому я задержал NewCode на пол-clk, чтобы ScanCodeT к этому моменту гарантированно устаканился.

 

К сожалению, это не поменяло вообще ничего. Далее перечитал Ваше сообщение и пришел к выводу, что Вы говорите о чем-то другом, но пока понять не могу...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

если у вас сигналы ScanCodeT и NewCode формируются по восходящему фронту clk то при задании стандартных констраинов на клок вида

Period = N, синтезатор следит чтобы эти сигналы оказывались во всех местах куда они должны дойти к следующему восходящему фронту клока.

 

Если же вы используете формируемый по восходящему фронту сигнал, по падающему фронту в надежде что у вас будет клок и еще половинка, то на самом деле у вас будет всего пол клока. Но синтезатор без дополнительных констраинов на установку и удержание сигнала за этим моментом не следит. И если они пишет что все констраины выполнились, то это не значит что сигнал начав свой подъем по восходящему фронту, в ближайший нисходящий фронт окажется везде в поднятом состоянии...

 

Или я что-то не так понял про задержку на полтакта?

В общем не стоит работать по разным фронтам клока, если это не требует особенно чем-то извне. Потому что в этом случае вы теряете проверки синтезатора

 

 

метастабильность про которую я писал - это для внешних асинхронных сигналов, или сигналов формируемых по разным клокам, если у вас один единый клок на всю схему, то это вас пока не касается.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

метастабильность про которую я писал - это для внешних асинхронных сигналов, или сигналов формируемых по разным клокам, если у вас один единый клок на всю схему, то это вас пока не касается.

 

Так какого фига оно не работает ??? :)

 

Вроде все перепробовал, что сам смог придумать, и что посоветовали... Последний вариант:

 

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 находится в активном состоянии один цикл клока, и у меня есть отдельный процесс, обеспечивающий это. Так вот, этот процесс не работал :) Как только исправил его, все завелось !

 

В любом случае, еще раз всем спасибо - все-равно узнал новые для себя вещи, да процесс сейчас намного более красивый, чем в моем первоначальном варианте.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...