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

Verilog. Проблема с асинхронным сбросом в always блоках

Задачка пустяковая - начать постижение верилога. По сути - описать сторожевой таймер.

Но, блин, не могу даже скомпилить проект.

 

Если "на пальцах", то вот...

post-29795-1429128050_thumb.png

При отсутствии сигнала Activate, счетчики должны находится в "нулях" и выход Alarm тоже.

В рабочем режиме - выход Alarm в нуле до тех пор, пока частота сигнала Charge выше, чем 50 раз за 10 секунд.

 

Пытался и в одном always блоке описать, и в отдельных, но что-то не складывается.

module PumpControl(
input clk_1Hz,
input pump,
input activate,

output reg alarm
);

//-------------------------------------------------------------------------------------------
reg [0:7] charge = 8'd0;		//	Счетчик необходимого кол-ва импульсов с датчика
reg [0:3] timer = 4'd0;			//	Таймер времени ожидания, по истечению которого - авария
parameter countMin = 8'd50;		//	Кол-во импульсов с датчика, меньше которого - появится ошибка
parameter waitingTime = 4'd10;		//	Время, за которое должно появится достаточное кол-во импульсов

always @(posedge pump)
begin
if(!activate || charge >= countMin) begin
	charge = 8'd0;
end else begin
	charge <= charge + 1'b1;
end
end

wire resetTimer;
assign resetTimer = (charge) ? 1'b1 : 1'b0;

always @(posedge clk_1Hz or posedge resetTimer)
begin
if(!activate) begin
	timer = 4'd0;
	alarm = 1'b0;
end else
if(timer < waitingTime) begin
	timer <= timer + 1'b1;
end else
if(timer >= waitingTime) begin
	alarm = 1'b1;
end

end

endmodule

 

Если закоментировать содержимое второго always, то проект собирается.

А в чем причина?

И как правильно реализовать сброс и синхронно и асинхронно одновременно?

 

 

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


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

Во втором always сигнал resetTimer описан как сброс, но внутри никак не используется. Посмотрите в логах почему компилятор ругается.

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


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

И как правильно реализовать сброс и синхронно и асинхронно одновременно?

 

Все асинхронные сигналы управления, перечисленные в always, должны быть в начале блока в условиях if, тогда они станут асинхронными сигналами управления.

 

always @(posedge clk_1Hz or posedge resetTimer)

if (resetTimer)

begin

... async ...

end else begin

... sync ...

end

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


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

Ужасный код.

Зачем вы используете > и <, вы не уверены что счетчик считает до 50?

Зачем разрядность 8 если вы считаете до 50?

 

Иф (цнт==0)

Цнт <=49

Елсе

Цнт <= цнт - 1

 

Операция ==0 значительно дешевле <Х

 

Асинхронное формирование сигнала сброса из 8-и разрядного регистра чревато возникновением паразитных фронтов (до 8шт), и ложных фронтов. Правильнее даже сказать они там будут всегда, но быстродействие фпга не позволит отработать большую часть из них.

 

Результат первого счетчика используется для формиования сигнала, который нигде не используется, компилятор его сократил.

 

Во втором счетчике ничего не регулирует регистр таймер. Аларм всегда будет 1.

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


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

Вот, как-то так:

 

Промежуточные выходы конца счета сделаны отдельными дополнительными регистрами, чтобы избежать там глитчей. Но, управление от "cnt1Q" я бы сделал асинхронным, так как не уверен, что он будет длиться достаточно, чтобы синхронно сбросить второй счетчик. То есть, схема может быть глючной изначально, по самой схеме.

 

reg [5:0] cnt1;
reg [3:0] cnt2;
reg Alarm;
reg Stop;
reg cnt1Q;

/* First counter */

always @(posedge Charge or posedge Activate)
if (Activate) cnt1 <= 6'd0;
else if (Stop || cnt1Q) cnt1 <= 6'd0;
else cnt1 <= cnt1 + 1'b1;

always @(posedge Charge or posedge Activate)
if (Activate) cnt1Q <= 1'b0;
else if (Stop)  cnt1Q <= 1'b0;
else cnt1Q <= (cnt1 == 6'd48);

/* Second counter */
always @(posedge clk1hz or posedge Activate)
if (Activate) cnt2 <= 4'd0;
else if (!Stop)
  if (cnt1Q) cnt2 <= 4'd0;
  else cnt2 <= cnt2 + 1'b1;

always @(posedge clk1hz or posedge Activate)
if (Activate) Stop <= 1'b0;
else if (!Stop) Stop <= (cnt2 == 4'd8);

/* Alarm */
always @*
if (Activate || cnt1Q) Alarm <= 1'b0;
else if (Stop) Alarm <= 1'b1;

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


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

always @(posedge Charge or posedge Activate)
if (Activate) cnt1 <= 6'd0;
else if (Stop || cnt1Q) cnt1 <= 6'd0;
else cnt1 <= cnt1 + 1'b1;

 

Как же вы пишите компактно блин.... мне кажется ваша страсть экономить заставила вас сэкономить на размере монитора:)

 

always @(posedge Charge or posedge Activate)
  begin
      if (Activate) 
         cnt1 <= 6'd0;
      else  if (Stop || cnt1Q) 
         cnt1 <= 6'd0;
      else 
         cnt1 <= cnt1 + 1'b1;
  end

 

 

 

 

 

А еще для ТС хочу добавить что верилог позволяет описывать не только схему, но и поведение. Иногда можно просто описать что хочется, и поглядеть какая из этого получиться схема. Правда многие такой подход отрицают:). Что известно про сигнал charge относительная клока 1 КГц? Потому что по схеме это асинхронные сигналы, и получиться их надо как-то синхронизовать, а то метастабильность, обсурд и коррупция...

 

И еще надо забывать программисткие перестраховки потому что >= жрет ресурсов больше чем ==,

i <= 0;
  ...
i <= i + 1;
if(i > 5)
  ...

жрет больше чем

i <= 5;
  ...
i <= i - 1;
if(i == 0)
  ...

 

много приемчиков как сэкономить лутики.... >7 проверять труднее чем == 8, если последние проверять по тому что появился четвертый бит и от 0 до 7 считать больше ресурсов чем от 1 до 8 в итоге:)

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


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

И еще надо забывать программисткие перестраховки потому что >= жрет ресурсов больше чем ==,
В машинах состояний такие перестраховки строго обязательны, иначе зависнет.

 

 

много приемчиков как сэкономить лутики.... >7 проверять труднее чем == 8, если последние проверять по тому что появился четвертый бит и от 0 до 7 считать больше ресурсов чем от 1 до 8 в итоге:)
Если мы говорим об экономии лутиков, и сравнение реализовано на лутах, то не всё ли равно, какую функцию над входными битами делать на этих лутах?

Если на раскиданных XORах - то другое дело, наверное, не проверял...

 

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


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

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

С чего вдруг? Это неверно! Если все правильно сделано ничего не зависнет. Даже default не нужен, если исключить помехи...

 

 

Если мы говорим об экономии лутиков, и сравнение реализовано на лутах, то не всё ли равно, какую функцию над входными битами делать на этих лутах?

если сравнение векторов - ЛУТ, если 1 бит, то без ЛУТа... и вопрос числа лутов, если сравнивать 32 битный вектор - много ЛУТов, если 1 бит из него то может и без ЛУТов... так что экономия по любому

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


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

ничего не зависнет. Даже default не нужен, если исключить помехи...
Вот не надо их исключать. Сталкивался с изменением состояния регистров, которые никто не трогал просто от наводки по эфиру. Рядом работал лазер. Всякое бывает. Вопрос вероятности. Я бы обязательно поставил default или аналог.

 

 

если сравнение векторов - ЛУТ, если 1 бит, то без ЛУТа... и вопрос числа лутов, если сравнивать 32 битный вектор - много ЛУТов, если 1 бит из него то может и без ЛУТов... так что экономия по любому
Дак как можно сравнивать на больше однобитный сигнал? Речь идёт о шине. Значит о ЛУТе. Пусть 32-битная шина. Какая разница ЛУТу, какую функцию сравнения делать? У него всё равно таблица.

 

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


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

Вот не надо их исключать. Сталкивался с изменением состояния регистров, которые никто не трогал просто от наводки по эфиру. Рядом работал лазер. Всякое бывает. Вопрос вероятности. Я бы обязательно поставил default или аналог.

А вы знаете что ISE в ходе оптимизации его выкинет если у вас не стоит опции сделать безопасный автомат, а если стоит то насильно добавит с переходом в заданное состояние восстановления:) потому во всяком случае для ISE и для кейза в автоматах это без не имеет смысла, даже с помехами...

 

Дак как можно сравнивать на больше однобитный сигнал

допустим вам надо что-то отсчитать и когда стало больше 6 что-то сделать...

написав if(... > 6) - вы получаете сравнение с вектором...

но если вы начнете считать не с 0 до 7 (больше 6), а с 1 до 8, а в сравнении будет if(counter[3] == 1) - это будет 1 битный сигнал который может напрямую пойти на разрешение...

Битность сравнения тоже важна, лут то имеет ограниченное число входов 1- 4 бита - 1 ЛУТ, а 5-8 битов уже 3, по одному на каждые 4 бита и 1 на результат лутов...

 

даже имеет значение если addr - one hot как записать

case(addr)

1:

2:

4:

....

или

if (addr[1] == 1)

if (addr[2] == 1)

if (addr[4] == 1)

....

 

причем иногда как-то катастрофически имеет значение:(

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


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

А вы знаете что ISE в ходе оптимизации его выкинет если у вас не стоит опции сделать безопасный автомат, а если стоит то насильно добавит с переходом в заданное состояние восстановления:) потому во всяком случае для ISE и для кейза в автоматах это без не имеет смысла, даже с помехами...
В любом случае нужно иметь в виду, что помехи собьют автомат, и делать всё возможное, включая то, что Вы описали выше. Но также включая и сравнение не просто ==, а >.

 

 

но если вы начнете считать не с 0 до 7 (больше 6), а с 1 до 8, а в сравнении будет if(counter[3] == 1) - это будет 1 битный сигнал который может напрямую пойти на разрешение...
Ну это уже мелкие хитрости, я их не подразумевал, когда писал своё изначальное возражение. Тут цепи переноса являются этим самым сравнивателем, заместо лутов.

 

 

Битность сравнения тоже важна, лут то имеет ограниченное число входов 1- 4 бита - 1 ЛУТ, а 5-8 битов уже 3, по одному на каждые 4 бита и 1 на результат лутов...
В любом случае, если сравнение делается на лутах, то для выдачи результата той же шины на 32 бита потребуется каскадное соединение того же количества лутов, что при проверке на равенство, что при проверке больше.

 

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


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

Потому вторая хитрость проверять не на == константе, а на == 0, или меньше 0. В первом случае проверка ИЛИ по всем битам, во втором случае проверяем вообще знаковый бит.

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


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

А что толку, что это ИЛИ, если это на лутах реализовано? Лутам без разницы, какая функция. Съеденных лутов от этого не меньше

 

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


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

что при проверке на равенство, что при проверке больше.

А вот тут Вы в корне не правы. Проверка на > или < - это сумматор (вычитатель, точнее), со всеми вытекающими цепями переноса. Проверка на == и != это древесная структура XOR - OR - ... - OR, которая в принципе быстрее сумматора, причем убыстрение растет экспоненциально с увеличением разрядности.

 

А автор темы вообще пропал...

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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