реклама на сайте
подробности

 
 
> Боремся с защёлками, то бишь latch'ами
Vincent Vega
сообщение Dec 11 2004, 22:26
Сообщение #1


Участник
*

Группа: Свой
Сообщений: 46
Регистрация: 26-09-04
Пользователь №: 721



Введение (можно не читать smile.gif):

к ПЛИС подключено статическое асинхронное ОЗУ 32 кБ (имена выводов начинаются с MEM_)
имеется два счётчика адреса addr1 и addr2. По первому адресу при наступлении некоторых условий нужно читать данные из ОЗУ (после чего адрес инкрементировать), при наступлении другого условия нужно записывать
данные в ОЗУ по второму адресу.
сигнал write_MEM управляет тристабильным буфером и когда он равен '1' MEM_D настроена на запись (т.е. вывод данных из ПЛИС)


Суть вопроса (желательно ознакомиться перед ответом):

После компиляции в Quartus получаю, что MEM_A, MEM_CS, MEM_RD, MEM_WR
являются выходами защёлок и, соотвественно, предупреждение об этом от design Assistant: "Design should not contain combinational loops". Как побороть эту неприятность (на форуме неоднократно слышал высказывания, что люди умудряются делать проекты вообще без защёлок).

Собственно, кусок кода с пояснениями:

Схему описываю как автомат, изменение состояний которого происходит по положительному фронту синхросигнала CLK.
Ниже приводится часть кода процесса, формирующего значение выходов автомата, в зависимости от его текущего состояния.
if (CLR = '1') then
MEM_CS <= '1';
MEM_RD <= '1';
MEM_WR <= '1';
inc_addr1 <= '0';
write_MEM <= '1';
else
case CurState is
when sStartReadMem =>
write_MEM <= '0';
MEM_A(14 downto 0) <= addr1 (14 downto 0);
MEM_CS <= '0';
MEM_RD <= '0';
when sEndReadMem =>
MEM_CS <= '1';
MEM_RD <= '1';
data(7 downto 0) <= MEM_D(7 downto 0);
inc_addr1 <= '1';
when sSaveData =>
write_MEM <= '0';
inc_addr1 <= '0';
-------

when sStartWriteMem =>
MEM_A(14 downto 0) <= addr2(14 downto 0);
MEM_CS <= '0';
MEM_WR <= '0';
when sEndWriteMem =>
MEM_CS <= '1';
MEM_WR <= '1';

Сопутствующий вопрос:
Как наиболее глюкобезопасно сделать инкрементацию addr1 после чтения? Сейчас для этого (см. выше) я изменяю состояние сигнала inc_addr1, который подан на вход разрешения счёта счётчика, реализованного на базе lpm_counter. Синхросигналом для счётчика является инвертированная частота CLK. Т.е. всё построено на том, что изменение состояния автомата (а значит и inc_addr1) происходит по положительному фронту CLK, а инкремент счётчика addr1 по отрицательному.
Существуют опасения, что при некоторых вариантах разводки кристалла установление значения inc_addr1 может произойти позднее, чем через пол-такта CLK=60MГц, и соотвественно инкремент не произойдёт.

приветствуются ссылки на литературу и исходники, где можно на конкретных примерах посмотреть как решаются такие вопросы.

Спасибо
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
vetal
сообщение Dec 13 2004, 14:38
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 2 095
Регистрация: 27-08-04
Из: Россия, СПб
Пользователь №: 553



Определить логику до конца - описать вае возможные ее комбинации.
Один из выходов - поставить нечто вроде "MEM_CS<='0'" или "MEM_A(14 downto 0)<=(others=>'-')", для всех сикналов срвзу после "process (..)\n\tbegin\n\t\t", и это будут значения принимаемые логикой, если она не описана. Желательно в каждом case->when описывать все сигналы и переменные используемые в process'е(это расширение указанного выше). настоятельно рекомендую устранить все латчи(приведенная конструкция с клоком просто заменит латчи на синхронные триггеры), т.к. рано или поздно они вас укусят.
В вашем примере достадочно будет сделать асинхронные выходы автомата, и не плодить регистры, для этого можно исролизовать -
MEM_CS<= '1' when state=sEndReadMem else '0';. естественно вне процесса, это пожалуй будет самый простой для вас вариант.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 22:39
Рейтинг@Mail.ru


Страница сгенерированна за 0.01365 секунд с 7
ELECTRONIX ©2004-2016