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

Добрый день. Пытаюсь адаптировать свой verilog, проверенный на fpga, для реализации в кремнии.

Периодически возникают те или иные вопросы, ответ на которые хочется найти тут, у спецов.

Первый вопрос:

 

Представим 8-разрядный счетчик, считающий по клоку. По достижению им числа 100 нужно переключиться в режим 1, по достижению 200 - в режим 2 и остаться в нем до сброса.

Раньше, в ПЛИС (в связи с избыточностью ячеек), я бы сделал так:

reg [7:0]cnt;
always @(posedge clk, negedge nrst) 
begin
    if (~nrst) cnt <= 0;
    else begin
        if(cnt<200) cnt <=cnt + 1'b1;
    end
end

always @*
begin
    if(cnt<100) mode <= 0;
    else if(cnt <200) mode <= 1;
    else mode <= 2;
end

 

Теперь, представляю, во что выльется этот код: синтезатор реализует 3 компаратора (причем для определения диапазона) из простых элементов для декодирования значения счетчика. Думаю, как упростить схему. Рождается код:

reg [7:0]cnt;
always @(posedge clk, negedge nrst) 
begin
    if (~nrst) begin
        cnt <= 0;
        mode <= 0;
    end
    else begin
cnt <= cnt+1;
        if(cnt==100 || cnt==200) mode <= mode+1;
    end
end

Тут уже компарирование не диапазона, а конкретных значений, зато логика mode становится синхронной.

Проверил в DC - действительно, экономия по площади и кол-ву ячеек - почти в 2 раза.

Не имеет ли второй вариант каких-то подводных камней?

Изменено пользователем drozel

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


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

1. Словестное описание не соответствует verilog'у.

2. Во втором варианте нет прибавления к счетчику.

3. Во втором случае mode будет меняться на 1 клок позже. (возможно, нужно будет сравнивать с 99 и 199)

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


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

1. Словестное описание не соответствует verilog'у.

2. Во втором варианте нет прибавления к счетчику.

3. Во втором случае mode будет меняться на 1 клок позже. (возможно, нужно будет сравнивать с 99 и 199)

1. Сорри, делал второпях, не суть, просто пример. Поправил.

2. Опять же недоглядел. Поправил.

3. Опять суть в константах, не критично.

 

Спасибо, из вашего ответа следует "и так и так можно делать, т.к. второй вариант более экономичен, можно и нужно делать по второму варианту"?

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


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

always @*

begin

if(cnt<100) mode <= 0;

else if(cnt <200) mode <= 1;

else mode <= 2;

end[/code]

 

 

 

Не имеет ли второй вариант каких-то подводных камней?

Вот первый вариант - асинхронный. И он-то как раз "имеет", потому как "cnt" переключается далеко не одновременно. Да и еще компаратор свое добавит. А потому "mode" может переключаться как угодно из-за гонки фронтов... В зависимости от погоды и настроения...

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


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

Вот первый вариант - асинхронный. И он-то как раз "имеет", потому как "cnt" переключается далеко не одновременно. Да и еще компаратор свое добавит. А потому "mode" может переключаться как угодно из-за гонки фронтов... В зависимости от погоды и настроения...

Хорошее замечание, спасибо.

Кстати, отловил еще одно отличие: в синхронном примере нет насыщения счетчика. После того, как добавил, площадь второго варианта стала почти в 1.5 раза больше. Т.е. синхронный более накладный. Видимо, все таки синтезер очень сильно упрощает логику сравнения, даже если речь идет о диапазонах.

Еще, в синхронном отстал один critical path.

 

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


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

Хорошее замечание, спасибо.

Кстати, отловил еще одно отличие: в синхронном примере нет насыщения счетчика. После того, как добавил, площадь второго варианта стала почти в 1.5 раза больше. Т.е. синхронный более накладный. Видимо, все таки синтезер очень сильно упрощает логику сравнения, даже если речь идет о диапазонах.

Еще, в синхронном отстал один critical path.

1. дайте посмотреть на код.

2. что значит "отстал один critical path"?

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


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

1. дайте посмотреть на код.

2. что значит "отстал один critical path"?

module top (
    input clk,
    input nrst,
    output reg [1:0]mode
);

reg [7:0]cnt;
always @(posedge clk, negedge nrst) 
begin
    if (~nrst) begin
        cnt <= 0;
        mode <= 0;
    end
    else begin
        if(cnt<200)    cnt <= cnt + 1;
        if(cnt==99 || cnt==199) mode <= mode+1;
    end
end

endmodule

Вы говорили про тайминги. Я не до конца понял, что Вы имели ввиду, посмотрел отчет по slack. У варианта 2 они чуть лучше, кроме одного пути: младший бит cnt - сумматор - старший бит через логику.

 

К слову про глитчи: предположим, что на выходе mode еще одна защелка, которая защелкивает по окончанию счета.

 

Вариант 2:

post-62650-1450357785_thumb.png

Вариант 1:

post-62650-1450357873_thumb.png

Изменено пользователем drozel

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


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

Хорошее замечание, спасибо.

Кстати, отловил еще одно отличие: в синхронном примере нет насыщения счетчика. После того, как добавил, площадь второго варианта стала почти в 1.5 раза больше. Т.е. синхронный более накладный. Видимо, все таки синтезер очень сильно упрощает логику сравнения, даже если речь идет о диапазонах.

На самом деле не все так однозначно... Вы пишите (cnt<100)... А что будет, если не 100, а 127? И не 200, а 255? Тогда компараторы могут просто сравнивать только старшие разряды и логика значительно сократится... Т.е. если старший разряд 0, то mode = 0, если 1, то и mode = 1, а если два старших разряда 1, то mode = 2...

 

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


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

1. А если поменять "if(cnt<200) cnt <= cnt + 1;" на "if(mode != 2) cnt <= cnt + 1'b1;"?

2. Для такого маленького дизайна не стоит обращать на critical path. В любом случае, это всё поменяется при placement.

 

На самом деле не все так однозначно... Вы пишите (cnt<100)... А что будет, если не 100, а 127? И не 200, а 255? Тогда компараторы могут просто сравнивать только старшие разряды и логика значительно сократится... Т.е. если старший разряд 0, то mode = 0, если 1, то и mode = 1, а если два старших разряда 1, то mode = 2...

Ага, давайте сделаем 128 итераций вместо 100. Какая разница? Ну результат шифрования будет неверный, зато гейты съэкономили.

 

 

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


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

Я бы еще посоветовал всегда полностью прописывать разрядности шин. Потому как то, что Вы не указали явно, синтезатору приходится додумывать. А чем больше он додумывает, тем больше шанс, что сделает неверно

 

begin
    if (~nrst) begin
        cnt[7:0] <= 8'h0;
        mode[1:0] <= 2'h0;
    end
    else begin
        if(cnt[7:0]<200)    cnt[7:0] <= cnt[7:0] + 8'h1;
        if(cnt[7:0]==99 || cnt[7:0]==199) mode[1:0] <= mode[1:0]+2'h1;
    end
end

 

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

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


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

Ага, давайте сделаем 128 итераций вместо 100. Какая разница? Ну результат шифрования будет неверный, зато гейты съэкономили.

никто не заставляет считать с нуля. после 128 счетчик может сразу внезапно стать 28. и тогда останутся прежние 100 шагов, а компаратор упростится =)

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


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

никто не заставляет считать с нуля. после 128 счетчик может сразу внезапно стать 28. и тогда останутся прежние 100 шагов, а компаратор упростится =)

внезапно = дополнительные гейты и не факт что их будет меньше.

 

Я бы еще посоветовал всегда полностью прописывать разрядности шин. Потому как то, что Вы не указали явно, синтезатору приходится додумывать. А чем больше он додумывает, тем больше шанс, что сделает неверно

А я бы такого не делал. Будет очень сложно потом увеличить разрядность или что-то поменять. Синтесайзер достаточно умный чтобы такие вещи понимать.

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


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

1. А если поменять "if(cnt<200) cnt <= cnt + 1;" на "if(mode != 2) cnt <= cnt + 1'b1;"?

Попробовал. Ожидаемо уменьшилось кол-во гейтов: теперь на входе каждого регистра-счетчика - по мультиплексору 2 в 1. На вход управления приходит mode[1]. Т.е. по сравнению с предыдущим вариантом просто упростилась логика определения условия остановки. Спасибо за идею.

 

Я бы еще посоветовал всегда полностью прописывать разрядности шин. Потому как то, что Вы не указали явно, синтезатору приходится додумывать. А чем больше он додумывает, тем больше шанс, что сделает неверно

Я на FPGA частенько напарывался на такую глупую ошибку: есть готовый модуль с шиной на выходе

module mod1(
input [7:0]a,
output c,
output [7:0]b);

используешь его в проекте, пишешь

mod1 mod(
.a(a),
.c(c),
.b(b);

а a,b,c - не объявлены заранее. Синтезатор создает их сам, только все шириной 1 бит. Потом только в RTL или в симуляции докапываешься, в чем дело.

Тогда я принял за правило писать .b(b[7:0]) - так, если она не объявлена, синтезатор хотя бы ругнется.

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

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


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

а a,b,c - не объявлены заранее. Синтезатор создает их сам, только все шириной 1 бит. Потом только в RTL или в симуляции докапываешься, в чем дело.

Есть замечательная директива

`implicit_nettype none

 

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


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

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

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

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

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

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

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

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

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

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