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

Правильное описание счетчика на VHDL

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

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY COUNTER_SCLR IS
   GENERIC
   (
       WIDTH      : INTEGER := 512
   );
   PORT
   (
       CLK                     : IN  STD_LOGIC;
       SCLR                    : IN  STD_LOGIC;
       DATA_OUT                : OUT INTEGER RANGE 0 TO WIDTH - 1 := 0
   );
END ENTITY;
ARCHITECTURE RTL OF COUNTER_SCLR IS
   SIGNAL COUNTER : INTEGER RANGE 0 TO WIDTH - 1 := 0;
BEGIN
   COUNTER_PROC : PROCESS
   (
       CLK
   )
   BEGIN
       IF (RISING_EDGE(CLK)) THEN                            
           IF (COUNTER >= WIDTH - 1) THEN
               COUNTER <= 0;
           ELSE
               COUNTER <= COUNTER + 1;
           END IF;
           IF (SCLR = '1') THEN
               COUNTER <= 0;
           END IF;
       END IF;
   END PROCESS COUNTER_PROC;               
   DATA_OUT <= COUNTER;
END ARCHITECTURE;

На RTL модели видно 2 ряда мультиплексоров, один ряд для синхронного сброса, другой ряд для сброса по условию: когда счетчик досчитал до условия сброса (в данном случае во всех разрядах единицы) то его сбросить. Логика понятная и правильная с точки зрения описания текста.

image.png

image.png

 

Но вот если этот же счетчик описать так:

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY COUNTER_SCLR IS
   PORT
   (
       CLK                     : IN  STD_LOGIC;
       SCLR                    : IN  STD_LOGIC;
       DATA_OUT                : OUT STD_LOGIC_VECTOR(8 DOWNTO 0)
   );
END ENTITY;

ARCHITECTURE RTL OF COUNTER_SCLR IS
   SIGNAL COUNTER : STD_LOGIC_VECTOR(8 DOWNTO 0);
BEGIN
   COUNTER_PROC : PROCESS
   (
       CLK 
   )
   BEGIN
       IF (RISING_EDGE(CLK)) THEN                            
           COUNTER <= STD_LOGIC_VECTOR(UNSIGNED(COUNTER) + 1);
           IF (SCLR = '1') THEN
               COUNTER <= (OTHERS => '0');
           END IF;
       END IF;
   END PROCESS COUNTER_PROC;               
   DATA_OUT <= COUNTER;
END ARCHITECTURE;

 

То видно, что ряд мультиплексоров и схема сравнения была убрана, поскольку мы это и не описывали.

Казалось бы, поведение счетчиков абсолютно одинаковое, но т.к мы работаем не с INTEGER а c SLV, то счетчик автоматически обнуляется, при переполнении. Да и максимальная частота проекта выросла, что не может не радовать.

image.png

image.png

 

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

 

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY COUNTER_SCLR IS
   GENERIC
   (
       WIDTH      : INTEGER := 511
   );
   PORT
   (
       CLK                     : IN  STD_LOGIC;
       SCLR                    : IN  STD_LOGIC;
       DATA_OUT                : OUT INTEGER RANGE 0 TO WIDTH-1
   );
END ENTITY;

ARCHITECTURE RTL OF COUNTER_SCLR IS
   SIGNAL COUNTER: INTEGER RANGE 0 TO WIDTH-1;
BEGIN
   GENERATING_FULL_COUNTER : FOR I IN 1 TO 30 GENERATE
       GENERATING_COUNTER:  IF (2**I = WIDTH) GENERATE  
           COUNTER_PROC : PROCESS
           (
               CLK
           )
               VARIABLE COUNTER : STD_LOGIC_VECTOR(I-1 DOWNTO 0);
           BEGIN    
               IF (RISING_EDGE(CLK)) THEN                            
                   COUNTER := STD_LOGIC_VECTOR(UNSIGNED(COUNTER) + 1);
                   IF (SCLR = '1') THEN
                       COUNTER := (OTHERS => '0');
                   END IF;
               END IF;
           DATA_OUT <= TO_INTEGER(UNSIGNED(COUNTER));
           END PROCESS COUNTER_PROC;               

       END GENERATE;
   END GENERATE;

   GENERATING_SMALL_COUNTER:  IF (WIDTH /= 2)    AND 
                                 (WIDTH /= 4)    AND 
                                 (WIDTH /= 8)    AND 
                                 (WIDTH /= 16)   AND 
                                 (WIDTH /= 32)   AND 
                                 (WIDTH /= 64)   AND 
                                 (WIDTH /= 128)  AND 
                                 (WIDTH /= 256)  AND
                                 (WIDTH /= 512)  AND
                                 (WIDTH /= 1024) AND
                                 (WIDTH /= 2048) GENERATE -- ИТД...
       COUNTER_PROC : PROCESS
       (
           CLK
       )
       BEGIN
           IF (RISING_EDGE(CLK)) THEN                         
               IF (COUNTER >= WIDTH-1) THEN
                   COUNTER <= 0;
               ELSE
                   COUNTER <= COUNTER + 1;
               END IF;
               IF (SCLR = '1') THEN
                   COUNTER <= 0;
               END IF;
           END IF;
       END PROCESS COUNTER_PROC;               
       DATA_OUT <= COUNTER;
   END GENERATE; 
END ARCHITECTURE;

На альтеровское описание счетчика, которое есть в шаблонах, Modelsim орёт благим матом, поскольку там нет условия обнуления счетчика. А можно ли это как-то красивее сделать, чем я описал ?

 

 

 

 

 

 

 

 

 

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


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

Integer или SLV роли не играют. Лишний мультиплексор в первом примере появляется из-за лишней проверки. Если её убрать, то получится точно такая же схема как во втором примере. Разрядность переменной типа integer ограничена до 9 бит на этапе описания переменной.

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


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

Integer или SLV роли не играют. Лишний мультиплексор в первом примере появляется из-за лишней проверки. Если её убрать, то получится точно такая же схема как во втором примере. Разрядность переменной типа integer ограничена до 9 бит на этапе описания переменной.

Именно. Вот только Modelsim откажется это симулировать...

 

.# ** Fatal: (vsim-3421) Value 256 for DATA_OUT is out of range 0 to 255.

# Time: 6450 ns Iteration: 3 Signal: /counter_sclr_vhd_tst/DATA_OUT File:

 

Мне не жалко лишних ресурсов в ПЛИС. Это капля в море... Хотя может и пригодиться когда-нибудь сделать очень быстрый счетчик. Хотя там наверно надо будет делать ускоренный перенос.

Изменено пользователем Flip-fl0p

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


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

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

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

 

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

 

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

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


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

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

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

 

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

 

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

Вопрос возник из-за разной максимальной частоты схемы, которую выдает TimeQuest. Вот и решил разобраться. Может я просто что-то неправильно понимаю.

На технологическом виде схемы создаются разные, я проверял. А как тогда описывать по поведению ?

А проверка нулевого значения это Вы имеете ввиду вычитающий счетчик ?

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


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

А как тогда описывать по поведению ?

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

А проверка нулевого значения это Вы имеете ввиду вычитающий счетчик ?

Имеется ввиду логическая операция ИЛИ.

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


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

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

 

Имеется ввиду логическая операция ИЛИ.

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

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

Но вот одну схему Modelsim воспринимает нормально, выдав предупреждение о переполнении разрядов, что опять же вполне логично. А вот другую схему забраковывает, ругаясь на то, что INTEGER вышел за диапазон счета.

Это несколько некорректное поведение симулятора...

Конечно можно оставить как есть, и забить на это дело. В конце-концов фиг с ним, с лишним мультиплексором. Капля в море. У меня пока не встречалось задач, где счётчик считать не успевает. Пока не встречалось...

Но в качестве самообразования хотелось бы знать, а как правильно делать.

Изменено пользователем Flip-fl0p

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


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

Именно. Вот только Modelsim откажется это симулировать...

 

Ну дык зайти с другого фланга можно, или я что-то не понимаю.

IF (COUNTER < WIDTH - 1) THEN
COUNTER <= COUNTER + 1;
ELSE
COUNTER <= 0;
END IF;

 

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

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


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

Ну дык зайти с другого фланга можно, или я что-то не понимаю.

IF (COUNTER < WIDTH - 1) THEN
COUNTER <= COUNTER + 1;
ELSE
COUNTER <= 0;
END IF;

 

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

А я и работаю только с пакетом NUMERIC_STD.

А смысл в том, что такая конструкция вполне рабочая, прекрасно работает в Modelsim и синтезируется.

        IF (RISING_EDGE(CLK)) THEN                            
            COUNTER <= STD_LOGIC_VECTOR(UNSIGNED(COUNTER) + 1);
            IF (SCLR = '1') THEN
                COUNTER <= (OTHERS => '0');
            END IF;
        END IF;

 

Аналогичная конструкция, но объявленная через тип INTEGER, прекрасно синтезируется, моделируется в Quartus. Но Modelsim ругается благим матом на неё.

        IF (RISING_EDGE(CLK)) THEN        
            COUNTER <= COUNTER + 1;
            IF (SCLR = '1') THEN
                COUNTER <= 0;
            END IF;
        END IF;

 

Эти 2 конструкции одинаково ложатся в ячейки ПЛИС поскольку на технологических картах выглядят одинаково.

 

Более того конструкция ,предложенная специалистами от Altera, которая находиться в шаблонах кода так-же взывает ругань у Modelsim.

process (clk)
        variable   cnt           : integer range MIN_COUNT to MAX_COUNT;
    begin
        if (rising_edge(clk)) then

            if reset = '1' then
                -- Reset the counter to 0
                cnt := 0;

            elsif enable = '1' then
                -- Increment the counter if counting is enabled               
                cnt := cnt + 1;

            end if;
        end if;

        -- Output the current count
        q <= cnt;
    end process;

 

 

 

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


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

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

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

 

зы. Шаблон альтеры позабавил.

ззы. Тут народ ругается, что в ISIM по умолчанию проверка выключена. https://forums.xilinx.com/t5/Simulation-and...-p/368031#M7970

зззы. Нашел опцию для ModelSim: [-norangecheck]

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


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

Какие-то странные костыли у вас с симулятором. Сам VHDL я не изучал, но читая форум складывается впечатление, что язык этот делает все, чтобы усложнить жизнь. Может быть вам лучше посмотреть в сторону Verilog? :rolleyes:

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


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

Какие-то странные костыли у вас с симулятором. Сам VHDL я не изучал, но читая форум складывается впечатление, что язык этот делает все, чтобы усложнить жизнь. Может быть вам лучше посмотреть в сторону Verilog? :rolleyes:

Ну в VHDL есть такое что надо одно и тоже в нескольких местах писать, а как чуть не так и синтез с моделированием разошлись:)

 

 

 

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

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

 

 

 

 

 

 

 

 

 

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


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

Ну в VHDL есть такое что надо одно и тоже в нескольких местах писать, а как чуть не так и синтез с моделированием разошлись :)
Вы, кажется, на VHDL не пишете. Но мнение имеете.

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

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


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

Вы, кажется, на VHDL не пишете. Но мнение имеете.

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

Ну зачем что-то делать чтобы иметь мнение?:)

Я достаточно плотно писал на VHDL в начале карьеры, потом перешел на Verilog так что я могу сравнивать.

Синтаксис Verilog очень далек от совершенства, но в целом он удобнее чем VHDL.

 

Синтаксис и организация кода.

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


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

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

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

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

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

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

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

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

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

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