anatole 0 29 апреля, 2016 Опубликовано 29 апреля, 2016 · Жалоба Здравствуйте. Начал осваивать ModelSim и натолкнулся на такие грабли. Имеется следующий упрощенный код на VHDL, при компиляции его в Quartus 9.1 и последующей временной симуляции в Quartus все замечательно. library ieee; use ieee.std_logic_1164.all; entity cnt is generic ( constant CNT_MAX : positive := 5 ); port ( rst : in std_logic; clk : in std_logic; ena : out std_logic ); end entity; architecture arc of cnt is signal cnt : natural range 0 to CNT_MAX - 1; begin process (all) begin if (rst = '1') then cnt <= 0; elsif (rising_edge(clk)) then cnt <= cnt + 1; --- !!! ОШИБКА !!! if (cnt = CNT_MAX - 1) then cnt <= 0; end if; end if; end process; process (all) begin if (rst = '1') then ena <= '0'; elsif (rising_edge(clk)) then if (cnt = CNT_MAX - 1) then ena <= '1'; else ena <= '0'; end if; end if; end process; end; Но при функциональной симуляции в ModelSim выскакивает следующая ошибка: # ** Fatal: (vsim-3421) Value 5 is out of range 0 to 4. на строке с коментарием. Я понимаю откуда она возникла. Вопрос в том, как ее обходить? Предложения: 1. не использовать числовые типы, а только массивы битов; 2. задавать какие-нибудь атрибуты для симуляции; 3. не использовать такую манеру написания кода, а явно прописывать для данного примера изменение сигнала cnt по условию else условного оператора. Но тогда много придется править для случаев, в которых сигнал сбрасывается в определенных условиях оператора case. Подскажите, как правильно поступить? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 14 29 апреля, 2016 Опубликовано 29 апреля, 2016 · Жалоба 1. не использовать числовые типы, а только массивы битов; Да. 2. задавать какие-нибудь атрибуты для симуляции; Никакие атрибуты не помогут. Грубо говоря, выход за границы массива контролируется самим языком -- он не даёт вам прострелить себе ногу. 3. не использовать такую манеру написания кода, а явно прописывать для данного примера изменение сигнала cnt по условию else условного оператора.В любом случае надо не допускать выхода за грницу массива. Поэтому сначала проверяем, а потом или сбрасываем счётчик, или делаем инкремент/декремент. Это, кстати, надо делать вне зависимости от того, целочисленный счётчик или битовый. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tausinov 0 29 апреля, 2016 Опубликовано 29 апреля, 2016 · Жалоба Проблема как в типе, так и в логике работы. if (cnt= CNT_MAX- 1) then cnt<= 0; else cnt<= cnt+ 1; end if; Если использовать тип unsigned, то переполнение не будет приводить к ошибке, и получится удобный счетчик по модуля 2^N Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 29 апреля, 2016 Опубликовано 29 апреля, 2016 · Жалоба Никакие атрибуты не помогут. Грубо говоря, выход за границы массива контролируется самим языком -- он не даёт вам прострелить себе ногу. В любом случае надо не допускать выхода за грницу массива. Поэтому сначала проверяем, а потом или сбрасываем счётчик, или делаем инкремент/декремент. Это, кстати, надо делать вне зависимости от того, целочисленный счётчик или битовый. Я только добавлю немного. Есть темплейты. И в Квартусе и в ИСЕ и в Моделсиме. И их использование позволит не наступать на совершенно типовые грабли... И даже более того. Я пользуюсь редактором EditPlus и у него можно создавать собственные темплейты из любимых кусков кода и потом вставлять их в нужное место просто одним кликом... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
anatole 0 29 апреля, 2016 Опубликовано 29 апреля, 2016 · Жалоба Всем, спасибо. Буду править код. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Timmy 1 29 апреля, 2016 Опубликовано 29 апреля, 2016 · Жалоба 3. не использовать такую манеру написания кода, а явно прописывать для данного примера изменение сигнала cnt по условию else условного оператора. Но тогда много придется править для случаев, в которых сигнал сбрасывается в определенных условиях оператора case. Подскажите, как правильно поступить? В сложных случаях можно присваивать промежуточные значения временной переменной с диапазоном, на единицу большим, а в конце процесса перенести окончательное значение в сигнал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр77 1 30 апреля, 2016 Опубликовано 30 апреля, 2016 · Жалоба Проблема как в типе, так и в логике работы. if (cnt= CNT_MAX- 1) then cnt<= 0; else cnt<= cnt+ 1; end if; Если использовать тип unsigned, то переполнение не будет приводить к ошибке, и получится удобный счетчик по модуля 2^N Поступаю, может сложнее, но в последствии гораздо удобнее. Через generic объявляю длины счетчиков и векторов (если их несколько). А затем использую такую конструкцию use ieee.numeric.atd.all; .... entity Name is generic( dwidth:natural:=16; max:natural:=65000); port(); end entity; .................. begin ........ process variable cnt:unsigned(dwidth-1 downto 0):=to_unsigned(0,dwidth);--объявляем счетчик constant zero:unsigned(dwidth-1 downto 0):=to_unsigned(0,dwidth);-- нуль constant step:unsigned(dwidth-1 downto 0):=to_unsigned(1,dwidth);--шаг для счетчика constant maxc:unsigned(dwidth-1 downto 0):=to_unsigned(max,dwidth);--предел счета ..... if(cnt>=maxc)then cnt:=zero; else cnt:=cnt+step; end if; По мне, такой код становится гибче за счет простой замены параметров в generic. И весьма удобно при структурном описании - задал параметр и вот новый счетчик с нужной разрядностью. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться