Jump to content

    

Подсчет импульсов

Уже по вопросу понятно, что он чайниковский :)

 

Задача банальная: подсчитывать некие импульсы, порожденные внутри ПЛИС т.е. изменяющиеся синхронно клоку (например, просто clk/N).

Я всегда поступал просто - подавал импульсы сразу на тактовый вход счетчика:

        
       always @(posedge pulse)
       begin
           count = count + 1'd1;
       end

Но роясь в чужих исходниках увидел, что люди делают это по-другому: на тактовый вход подают клок, а подсчитываемыми импульсами (укороченными до одного клока) разрешают счет:

       always @(posedge clk)
       begin
            if(short_pulse == 1) 
                count = count + 1'd1;
       end

C одной стороны, второй вариант вроде как правильнее с точки зрения "синхронной" идеологии, но это лишние аппаратные затраты на укорачивание импульса и проверку его уровня.

Так как лучше делать?

 

Share this post


Link to post
Share on other sites

в первом примере вы породили метастабильность и никак её не учитываете. (возможно, не знаете о последствиях?)

 

во втором случае при наличии констрейна на тактовый сигнал clk заботой о метастабильности занимаестя STA (static timing analyzer) вашего пакета САПР.

Share this post


Link to post
Share on other sites
C одной стороны, второй вариант вроде как правильнее с точки зрения "синхронной" идеологии, но это лишние аппаратные затраты на укорачивание импульса и проверку его уровня.

Так как лучше делать?

Вся логика должна быть синхронной, кроме разве что сброса или управляющих сигналов, но и они должны быть описаны с ограничениями. Что касается подсчета импульсов, то возьмите бОльшую частоту (больше чем в 2 раза) ну и как-то так:

reg [1:0] imp_r;

always @(posedge clk) imp_r<={imp_r[0],imp};

wire cnt_en=(imp_r==2'b10)?1'b1:1'b0;

 

Ну и по разрешению счета наворачивать счетчик.

Share this post


Link to post
Share on other sites
C одной стороны, второй вариант вроде как правильнее с точки зрения "синхронной" идеологии, но это лишние аппаратные затраты на укорачивание импульса и проверку его уровня.

Один триггер, задерживающий на такт clk ваш pulse, и потом проверка, что до триггера уже 1, а после еще 0. Так найдете фронт. Вот эти фронты и считайте. Фактически, то же самое укорачивание.

Share this post


Link to post
Share on other sites
Уже по вопросу понятно, что он чайниковский :)

 

 

C одной стороны, второй вариант вроде как правильнее с точки зрения "синхронной" идеологии, но это лишние аппаратные затраты на укорачивание импульса и проверку его уровня.

Так как лучше делать?

На самом деле все, что происходит внутри ПЛИС и должно делаться по "укороченным импульсам". Так что никаких "лишних" затрат и не будет...

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

 

Share this post


Link to post
Share on other sites

wire pulse;

reg [2:0] front;

reg [15:0] a;

 

always @(posedge clk) front<={front[1:0],pulse};

always @(posedge clk) if (front==3'b011) a<=a+1;

 

 

Share this post


Link to post
Share on other sites
always @(posedge clk) if (front==3'b011) a<=a+1;

 

А (front==3'b001) хуже или без разницы?

 

 

if(short_pulse == 1)

 

А short_pulse чему равен или это макрос некий?

 

Share this post


Link to post
Share on other sites

Лучше всего 4'b0011, чтобы одиночные палки не ловило. :rolleyes: А по мне, хватает 2'b01.

Share this post


Link to post
Share on other sites
А (front==3'b001) хуже или без разницы?

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

wire pulse;

reg [3:0] front;

reg [15:0] a;

always @(posedge clk) front<={front[2:0],pulse};

always @(posedge clk) if (front[3:1]==3'b011) a<=a+1;

Share this post


Link to post
Share on other sites

Спасибо за советы! Буду делать "по канонам" :)

 

Share this post


Link to post
Share on other sites

А насколько правильно делать импульсы так? :

pulse <= {s_reg, s} == 2'b01; // выделяем фронт
if(pulse) pulse <= 0;

Share this post


Link to post
Share on other sites
А насколько правильно делать импульсы так? :

pulse <= {s_reg, s} == 2'b01; // выделяем фронт
if(pulse) pulse <= 0;

А нинасколько...

Если импульсы приходят в ПЛИС извне, то все равно надо ставить синхронизатор из двух триггеров. И можно добавить еще один...

Или если эти импульсы медленные и есть опасность дребезга фронта, то лучше сразу сделать фильтр...

 

А если импульсы генерируются внутри, то значит идеология "генерирования, а потом выделения" сама по себе неправильная..

 

Share this post


Link to post
Share on other sites
А нинасколько...

Если импульсы приходят в ПЛИС извне, то все равно надо ставить синхронизатор из двух триггеров. И можно добавить еще один...

Или если эти импульсы медленные и есть опасность дребезга фронта, то лучше сразу сделать фильтр...

 

А если импульсы генерируются внутри, то значит идеология "генерирования, а потом выделения" сама по себе неправильная..

 

 

Дико извиняюсь, но я немного не то написал :)

Имелся в виду код вот такого вида:

if(cnt > 0) begin
    pulse <= 1; // генерируем импульс в начале счета
    cnt <= cnt - 1;
end
if(pulse) pulse <= 0;

Ну то есть идея такая что в одном месте (там где нужно сделать одиночный импульс во время какого-то длительного процесса) ставим сигнал в единицу, а потом на следующем же также его сбрасываем конструкцией if(pulse) pulse <= 0;. Насколько такой подход адекватен?

Edited by dmy

Share this post


Link to post
Share on other sites
Дико извиняюсь, но я немного не то написал :)

 

Ну то есть идея такая что в одном месте (там где нужно сделать одиночный импульс во время какого-то длительного процесса) ставим сигнал в единицу, а потом на следующем же также его сбрасываем конструкцией

Насколько такой подход адекватен?

Совершенно не "адекватен"!!! Даже идейно вреден...

Ставим автомат и таймер если нужно, только так... Автомат выдает "одиночный импульс", и на следующих тактах продолжает "длительного процесса"... Длительность которого задается таймером...

Подробнее могу по скайпу...

 

Share this post


Link to post
Share on other sites
...Насколько такой подход адекватен?

Подход адекватен, код неадекватен.

Надо учитывать, что в always-блоках все операторы выполняются последовательно.

Сам так пишу (без "else"):

pulse <= 0;
if(cnt == 0) pulse <= 1;

Второй оператор "отменяет" первый при выполнении условия "cnt == 0".

Условие "if(pulse)" - лишнее.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this