Jump to content
    

Правильное описание счетчика на 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 орёт благим матом, поскольку там нет условия обнуления счетчика. А можно ли это как-то красивее сделать, чем я описал ?

 

 

 

 

 

 

 

 

 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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:

 

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

Edited by Flip-fl0p

Share this post


Link to post
Share on other sites

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

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

 

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

 

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

Share this post


Link to post
Share on other sites

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

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

 

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

 

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

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

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

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

Share this post


Link to post
Share on other sites

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

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

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

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

Share this post


Link to post
Share on other sites

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

 

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

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

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

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

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

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

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

Edited by Flip-fl0p

Share this post


Link to post
Share on other sites

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

 

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

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

 

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

Share this post


Link to post
Share on other sites

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

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;

 

 

 

Share this post


Link to post
Share on other sites

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

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

 

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

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

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

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

 

 

 

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

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

 

 

 

 

 

 

 

 

 

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

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

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

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

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

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

 

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...