|
Модуль RTC. |
|
|
|
Sep 4 2017, 11:44
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Сделал модуль RTC Код entity RTC is port( RST : in Std_logic; CLK : in Std_logic; SECONDS : out Std_logic_vector(5 downto 0); MINUTES : out Std_logic_vector(5 downto 0); HOURS : out Std_logic_vector(4 downto 0); DAY : out Std_logic_vector(5 downto 0); MONTH : out Std_logic_vector(3 downto 0); YEAR : out Std_logic_vector(11 downto 0) ); end RTC; и вычисляю часы, минуты, дни и так далее. Но модуль надо инициализировать реальным временем. Получается надо сделать что то вроде такого Код entity RTC is port( RST : in Std_logic; CLK : in Std_logic; SECONDS_IN : in Std_logic_vector(5 downto 0); MINUTES_IN : in Std_logic_vector(5 downto 0); HOURS_IN : in Std_logic_vector(4 downto 0); DAY_IN : in Std_logic_vector(5 downto 0); MONTH_IN : in Std_logic_vector(3 downto 0); YEAR_IN : in Std_logic_vector(11 downto 0);
SET : in Std_logic;
SECONDS_OUT : out Std_logic_vector(5 downto 0); MINUTES_OUT : out Std_logic_vector(5 downto 0); HOURS_OUT : out Std_logic_vector(4 downto 0); DAY_OUT : out Std_logic_vector(5 downto 0); MONTH_OUT : out Std_logic_vector(3 downto 0); YEAR_OUT : out Std_logic_vector(11 downto 0) ); end RTC; набор для ввода и набор для вывода. А по другому никак?
Сообщение отредактировал Jenya7 - Sep 4 2017, 11:47
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 29)
|
Sep 4 2017, 11:53
|

В поисках себя...
   
Группа: Свой
Сообщений: 729
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140

|
Цитата(Jenya7 @ Sep 4 2017, 14:44)  Сделал модуль RTC Можно и по-другому. Один вход для загрузки данных назовём его DATA_LOAD : Std_logic_vector(N-1 downto 0); И загружаете по нему последовательно данные. Разрядность выбираете в зависимости от придуманного Вами алгоритма. Загружать данные можно последовательно сначала секунды, потом минуты, потом часы, потом дни, месяцы, года.
Сообщение отредактировал Flip-fl0p - Sep 4 2017, 11:53
|
|
|
|
|
Sep 4 2017, 12:42
|
Частый гость
 
Группа: Участник
Сообщений: 135
Регистрация: 19-10-13
Пользователь №: 78 795

|
Цитата(Jenya7 @ Sep 4 2017, 14:44)  Сделал модуль RTC и вычисляю часы, минуты, дни и так далее. Но модуль надо инициализировать реальным временем. Получается надо сделать что то вроде такого ... набор для ввода и набор для вывода. А по другому никак? Способов можно придумать, наверное, немало, но не будут ли они при этом более неудачными? Что не устраивает в этом варианте?
Сообщение отредактировал Tausinov - Sep 4 2017, 12:48
|
|
|
|
|
Sep 4 2017, 14:43
|
Местный
  
Группа: Участник
Сообщений: 221
Регистрация: 6-07-12
Пользователь №: 72 653

|
Цитата(Jenya7 @ Sep 4 2017, 17:10)  железо уже разработано. это старый проект. я только модули добавляю. Будьте готовы к тому, что такие часы будут не так точны, как специализированная RTC микросхема.
|
|
|
|
|
Sep 4 2017, 14:51
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Inanity @ Sep 4 2017, 19:43)  Будьте готовы к тому, что такие часы будут не так точны, как специализированная RTC микросхема. ну это да. но периодически происходит корекция. а как мне высчитать високосный год? в Си делал Код uint32_t IsLeapYear(uint32_t year) { if(((year%4==0)&&(year%100!=0))||(year%400==0)) return 1; else return 0; } а тут Код function IsLeapYear(year : integer) return std_logic_vector is variable ret : std_logic_vector; begin if( (year mod 4)= 0 and (year mod 100) /= 0 or (year mod 400) = 0) then ret := 1; else ret := 0; end if; return ret; end function IsLeapYear; ругается Error (10500): VHDL syntax error at RTC.vhd(41) near text "or"; expecting ")", or "," Error (10500): VHDL syntax error at RTC.vhd(41) near text ")"; expecting "then" вроде со скобками все в порядке
|
|
|
|
|
Sep 4 2017, 15:19
|
Частый гость
 
Группа: Участник
Сообщений: 135
Регистрация: 19-10-13
Пользователь №: 78 795

|
Цитата(Jenya7 @ Sep 4 2017, 17:51)  Код function IsLeapYear(year : integer) return std_logic_vector is variable ret : std_logic_vector; begin if( (year mod 4)= 0 and (year mod 100) /= 0 or (year mod 400) = 0) then ret := 1; else ret := 0; end if; return ret; end function IsLeapYear; ругается Error (10500): VHDL syntax error at RTC.vhd(41) near text "or"; expecting ")", or "," Error (10500): VHDL syntax error at RTC.vhd(41) near text ")"; expecting "then" вроде со скобками все в порядке Возьмите в скобки операцию "И" вместе с операндами. Видимо, что-то с приоритетами операций. Ну и ret нужно все-таки значения std_logic_vector'а присваивать, а не целые числа.
Сообщение отредактировал Tausinov - Sep 4 2017, 15:19
|
|
|
|
|
Sep 4 2017, 15:29
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Tausinov @ Sep 4 2017, 20:19)  Возьмите в скобки операцию "И" вместе с операндами. Видимо, что-то с приоритетами операций. Ну и ret нужно все-таки значения std_logic_vector'а присваивать, а не целые числа. так тоже ругается Код function IsLeapYear(year : integer) return std_logic_vector is variable ret : std_logic_vector; begin if ( ((year mod 4) = 0) and ((year mod 100) /= 0) or ((year mod 400) = 0) ) then ret <= '1'; else ret <= '0'; end if; return ret; end function IsLeapYear;
|
|
|
|
|
Sep 4 2017, 15:31
|
Частый гость
 
Группа: Участник
Сообщений: 135
Регистрация: 19-10-13
Пользователь №: 78 795

|
Цитата(Jenya7 @ Sep 4 2017, 18:29)  так тоже ругается Код function IsLeapYear(year : integer) return std_logic_vector is variable ret : std_logic_vector; begin if ( ((year mod 4) = 0) and ((year mod 100) /= 0) or ((year mod 400) = 0) ) then ret <= '1'; else ret <= '0'; end if; return ret; end function IsLeapYear; Ага, еще не заметил: variable ret : std_logic_vector(0 downto 0); вместо variable ret : std_logic_vector; и значения в двойных кавычках должны быть вместо одинарных. Код library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
entity isLeapYear is end isLeapYear;
architecture behav of isLeapYear is
signal testYear : integer := 2008;
function IsLeapYear(year : integer) return std_logic_vector is variable ret : std_logic_vector(0 downto 0); begin if ((year mod 4 = 0 and year mod 100 /= 0) or (year mod 400 = 0)) then ret := "1"; else ret := "0"; end if;
return ret; end function IsLeapYear; begin
process variable temp : std_logic_vector(0 downto 0); begin temp := IsLeapYear(testYear); report "function result is " & integer'image(to_integer(unsigned(temp))); wait; end process;
end behav;
Сообщение отредактировал Tausinov - Sep 4 2017, 15:33
|
|
|
|
|
Sep 4 2017, 15:42
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Tausinov @ Sep 4 2017, 20:31)  Ага, еще не заметил: variable ret : std_logic_vector(0 downto 0); вместо variable ret : std_logic_vector; и значения в двойных кавычках должны быть вместо одинарных. Код library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
entity isLeapYear is end isLeapYear;
architecture behav of isLeapYear is
signal testYear : integer := 2008;
function IsLeapYear(year : integer) return std_logic_vector is variable ret : std_logic_vector(0 downto 0); begin if ((year mod 4 = 0 and year mod 100 /= 0) or (year mod 400 = 0)) then ret := "1"; else ret := "0"; end if;
return ret; end function IsLeapYear; begin
process variable temp : std_logic_vector(0 downto 0); begin temp := IsLeapYear(testYear); report "function result is " & integer'image(to_integer(unsigned(temp))); wait; end process;
end behav; да. спасибо. так компилируется. в конце концов вот такая петрушка получилась. CODE library IEEE; use IEEE.std_logic_1164.all; use ieee.numeric_std.all; use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity RTC is port( RST : in Std_logic; CLK : in Std_logic; SET :In Std_logic; SECONDS_SET : in Std_logic_vector(5 downto 0); MINUTES_SET : in Std_logic_vector(5 downto 0); HOURS_SET : in Std_logic_vector(4 downto 0); DAY_SET : in Std_logic_vector(5 downto 0); MONTH_SET : in Std_logic_vector(3 downto 0); YEAR_SET : in Std_logic_vector(11 downto 0); MILISECONDS : out Std_logic_vector(9 downto 0); SECONDS : out Std_logic_vector(5 downto 0); MINUTES : out Std_logic_vector(5 downto 0); HOURS : out Std_logic_vector(4 downto 0); DAY : out Std_logic_vector(5 downto 0); MONTH : out Std_logic_vector(3 downto 0); YEAR : out Std_logic_vector(11 downto 0) --DAY_OF_WEEK :in Std_logic_vector(3 downto 0) ); end RTC;
architecture STRUCTURE of RTC is
function IsLeapYear(year : integer) return std_logic_vector is variable ret : std_logic_vector(0 downto 0); begin if ((year mod 4 = 0 and year mod 100 /= 0) or (year mod 400 = 0)) then ret := "1"; else ret := "0"; end if; return ret; end function IsLeapYear;
type arr_type1 is array (0 to 12) of integer range 0 to 32; -- := (0,31,28,31,30,31,30,31,31,30,31,30,31); signal days_in_month : arr_type1 := (0,31,28,31,30,31,30,31,31,30,31,30,31);
signal count : integer := 1; signal tick_1ms : std_logic := '0';
signal milisec : integer range 0 to 1000 := 0; signal sec,min,hour : integer range 0 to 60 := 0; signal days : integer range 0 to 31 := 1; signal months : integer range 0 to 12 := 1; signal years : integer := 0;
signal days_per_month : integer range 0 to 31 := 0;
begin
MILISECONDS <= std_logic_vector(to_unsigned(milisec,10)); SECONDS <= std_logic_vector(to_unsigned(sec,6)); MINUTES <= std_logic_vector(to_unsigned(min,6)); HOURS <= std_logic_vector(to_unsigned(hour,5));
DAY <= std_logic_vector(to_unsigned(days,6)); MONTH <= std_logic_vector(to_unsigned(months,4)); YEAR <= std_logic_vector(to_unsigned(years, 12));
--clk generation. For 30 MHz clock this generates 1 milisec clock. process (CLK,RST)
begin
if (RST='1') then count <= 1; elsif (rising_edge(CLK) ) then count <= count + 1; if(count = 15000) then --15000000 tick_1ms <= not tick_1ms; count <= 1; end if; end if;
end process;
process (CLK,RST) begin
if (SET='1') then sec <= to_integer(unsigned(SECONDS_SET)); min <= to_integer(unsigned(MINUTES_SET)); hour <= to_integer(unsigned(HOURS_SET)); days <= to_integer(unsigned(DAY_SET)); months <= to_integer(unsigned(MONTH_SET)); years <= to_integer(unsigned(YEAR_SET)); elsif (rising_edge(tick_1ms) ) then milisec <= milisec + 1; if (milisec = 999) then milisec <= 0; sec <= sec+ 1; end if; if(sec = 59) then sec <= 0; min <= min + 1; end if; if(min = 59) then min <= 0; hour <= hour + 1; end if; if(hour = 23) then hour <= 0; days <= days + 1; if (months = 2) then --calculate days for february if (IsLeapYear(years) = 1) then days_per_month <= 29; else days_per_month <= 28; end if; else days_per_month <= days_in_month(months); end if; end if; if(days = days_per_month) then days <= 0; months <= months + 1; end if; if (months = 12) then months <= 0; years <= years + 1; end if; end if;
end process;
end STRUCTURE;
|
|
|
|
|
Sep 5 2017, 08:20
|

Утомлённый солнцем
     
Группа: Свой
Сообщений: 2 646
Регистрация: 15-07-06
Из: г.Донецк ДНР
Пользователь №: 18 832

|
Цитата(Flip-fl0p @ Sep 4 2017, 19:41)  Код use IEEE.STD_LOGIC_UNSIGNED.ALL; Уберите её, она лишняя. И не является стандартом. Без неё у меня векторы не складываются. Код library ieee; use ieee.std_logic_1164.all; --use ieee.STD_LOGIC_UNSIGNED.all; use ieee.NUMERIC_STD.all; ................................... signal cnt : STD_LOGIC_VECTOR(7 downto 0); begin process(Clk,rst) is if (RISING_EDGE(Clk)) then cnt <= cnt+1; ................... # Error: COMP96_0071: TestBench/modulator_TB.vhd : (182, 42): Operator "+" is not defined for such operands. А с ней всё o`k.
|
|
|
|
|
Sep 5 2017, 08:43
|

В поисках себя...
   
Группа: Свой
Сообщений: 729
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140

|
Так а вы счетчик объявите как тип UNSIGNED и тогда можно будет записать так: Код USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; --................................... SIGNAL CNT : UNSIGNED(7 DOWNTO 0); BEGIN PROCESS(CLK,RST) IS IF (RISING_EDGE(CLK)) THEN CNT <= CNT + "1"; --................... Или сразу преобразовывайте типы : Код USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; --................................... SIGNAL CNT : STD_LOGIC_VECTOR(7 DOWNTO 0); BEGIN PROCESS(CLK,RST) IS IF (RISING_EDGE(CLK)) THEN CNT := STD_LOGIC_VECTOR(UNSIGNED(CNT) + 1); А потом конвертируйте тип UNSIGNED в STD_LOGIC_VECTOR. Но это можно делать не всегда. Или объявите счетчик как INTEGER а потом преобразуйте INTEGER в STD_LOGIC_VECTOR средствами библиотеки NUMERIC_STD.
|
|
|
|
|
Sep 5 2017, 09:03
|

В поисках себя...
   
Группа: Свой
Сообщений: 729
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140

|
Цитата(_Anatoliy @ Sep 5 2017, 11:50)  В том то и дело...
А смысл? Имхо, проще подключить библиотеку и не париться. Смысл в том, что библиотека NUMERIC_STD является стандартизированной библиотекой. А библиотека STD_LOGIC_UNSIGNED -это не стандартизированная библиотека. Я например не могу дать гарантию того что это библиотека будет работать всегда одинаково в любой версии САПР, в следствии чего я не могу дать гарантии того, что мои ранее написанные проекты будут работать так, как они задумывались. Если САПР не менять и не обновлять (фиг его знает, что поменяют обновления), то вроде и не страшно... Но поскольку я начал изучать VHDL когда уже была разработана библиотека NUMERIC_STD то я сразу начал применять только её. Я всегда за строгое соблюдение стандарта, были прецеденты на прошлой работе когда отклонения от ГОСТ приводили к достаточно дорогим ошибкам....
|
|
|
|
|
Sep 5 2017, 09:42
|

В поисках себя...
   
Группа: Свой
Сообщений: 729
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140

|
Цитата(_Anatoliy @ Sep 5 2017, 12:25)  То-же верно. Я уже привык к NUMERIC_STD и не особо чувствую дискомфорта. Я считаю что главное понимать когда и зачем нужно применять ту или иную библиотеку.
|
|
|
|
|
Sep 8 2017, 10:41
|

В поисках себя...
   
Группа: Свой
Сообщений: 729
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140

|
Цитата(_Anatoliy @ Sep 5 2017, 15:46)  Ну да, так и делаю когда имею дело с шиной данных в блоках DSP. Но для банального счётчика считаю это лишним. А я вообще счетчики в отдельных модулях держу. Один раз описал его, отладил и больше к нему не возвращаюсь. Только в параметрах указываю значение максимального счета. Лично я так меньше ошибаюсь при написании проектов CODE Код LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL;
ENTITY COUNTER_ENA IS GENERIC ( MAX_VALUE : INTEGER := 126 -- До скольки считает счетчик(от нуля до MAX_VALUE) ); PORT ( CLK : IN STD_LOGIC; ENA : IN STD_LOGIC; DATA_OUT : OUT INTEGER RANGE 0 TO MAX_VALUE ); END ENTITY;
ARCHITECTURE RTL OF COUNTER_ENA IS FUNCTION LOG2 (MAX_VALUE : INTEGER) RETURN INTEGER IS -- Функция вычесления логарифма по основанию 2 для определения разрядности VARIABLE CNT : INTEGER := 0; -- Счетчик для подсчета количества делений на 2 VARIABLE TEMP : INTEGER := MAX_VALUE + 1; -- Делимое - максимальное количество состояний счетчика BEGIN WHILE (TEMP > 1) LOOP -- Пока делимое больше 1 совершаем цикл деления на 2 CNT := CNT + 1; -- Считаем количество циклов деления TEMP := TEMP/2; -- Делим число на 2 каждый цикл END LOOP; RETURN CNT; -- Значение счетчика и есть логарифм END LOG2; SIGNAL COUNTER_INTEGER : INTEGER RANGE 0 TO MAX_VALUE := 0; -- Счетчик обнуляемый условием максимального счета SIGNAL COUNTER_UNSIGNED : UNSIGNED(LOG2(MAX_VALUE)-1 DOWNTO 0) := (OTHERS => '0'); -- Счетчик с автоматическом обнулени при переполнении BEGIN
--================================================================================ ========================== -- Если максимальное значение счетчика переведенное в двоичное число не состоит из одних только единиц -- Значит у нас счетчик обнуляется значением максимального счета т.е до наступления переполнения разрядов --================================================================================ ========================== GEN_RST_COND : IF ( TO_UNSIGNED(MAX_VALUE,LOG2(MAX_VALUE) ) /= ( LOG2(MAX_VALUE)-1 DOWNTO 0 => '1' ) ) GENERATE CNT_PROC : PROCESS ( CLK ) BEGIN IF (RISING_EDGE(CLK)) THEN IF (ENA = '1') THEN -- Сигнал разрешения работы счетчика IF (COUNTER_INTEGER = MAX_VALUE) THEN -- При наступлении максимального значения счетчика COUNTER_INTEGER <= 0; -- Обнулим его ELSE COUNTER_INTEGER <= COUNTER_INTEGER + 1; -- Иначе будем его инкрементировать END IF; END IF; END IF; END PROCESS; DATA_OUT <= COUNTER_INTEGER; END GENERATE; --================================================================================ ========================== -- Если максимальное значение счетчика это (2**N - 1) -- Значит у нас полный счетчик, который обнуляется переполнением разрядов --================================================================================ ========================== GEN : FOR I IN 0 TO 30 GENERATE OVERFLOW : IF (2**I-1 = MAX_VALUE) GENERATE CNT_PROC : PROCESS ( CLK ) BEGIN IF (RISING_EDGE(CLK)) THEN IF (ENA = '1') THEN -- Сигнал разрешения работы счетчика COUNTER_UNSIGNED <= COUNTER_UNSIGNED + "1"; -- Инкрементируем его каждый такт END IF; END IF; END PROCESS; DATA_OUT <= TO_INTEGER(COUNTER_UNSIGNED); END GENERATE; END GENERATE; END ARCHITECTURE;
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|