Maverick_ 15 9 апреля, 2020 Опубликовано 9 апреля, 2020 · Жалоба Всем доброго дня :) Под конец рабочего дня ... голова не "варит" Реализация должна быть по сигналу прерывания на следующем шаге прерываться. Делать строго заданное количество шагов(периодов) (num_step в тестбенче). Можно ли ускорить работу (тактовую частоту) или/и упростить логику? Как по мне описание немного сложноватое... shim_fsm.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 9 апреля, 2020 Опубликовано 9 апреля, 2020 · Жалоба 10 минут назад, Maverick_ сказал: Всем доброго дня :) Под конец рабочего дня ... голова не "варит" Реализация должна быть по сигналу прерывания на следующем шаге прерываться. Делать строго заданное количество шагов(периодов) (num_step в тестбенче). Можно ли ускорить работу (тактовую частоту) или/и упростить логику? Как по мне описание немного сложноватое... shim_fsm.rar А для какого чипа делается ? Я сейчас собаку выгуляю и могу глянуть проект. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 9 апреля, 2020 Опубликовано 9 апреля, 2020 · Жалоба 1 minute ago, Flip-fl0p said: А для какого чипа делается ? Я сейчас собаку выгуляю и могу глянуть проект. Zynq / CycloneV SoC Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 10 апреля, 2020 Опубликовано 10 апреля, 2020 · Жалоба library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity shim_fsm is generic ( DATA_LENGTH : integer := 32 ); port ( CLK : in std_logic; -- system clock RST : in std_logic; -- low active synchronous reset start_work : in std_logic; -- start work divider : in std_logic_vector(DATA_LENGTH - 1 downto 0); num_step : in std_logic_vector(DATA_LENGTH - 1 downto 0); interrupt : in std_logic; -- start work count_step : out std_logic_vector(DATA_LENGTH - 1 downto 0); ready : out std_logic; ready_period_shim : out std_logic; pwm_out : out std_logic -- start work ); end entity; architecture RTL of shim_fsm is --=================================================================================== -- Константа для того, чтобы задать максимальное значение счетчика. -- Ибо 2**31 больше чем диапазон целых в VHDL. --=================================================================================== constant cnt_max_value : unsigned(DATA_LENGTH - 1 downto 0) := (others => '1'); type state_type is ( start_work_st, set_pwm_0_st , set_pwm_1_st , stop_st ); signal press_state, next_state : state_type; --=================================================================================== -- --=================================================================================== signal reg_divider_data_sload : unsigned(DATA_LENGTH - 1 downto 0); signal reg_divider_is_zero : std_logic; signal reg_divider_sld_ena : std_logic; signal reg_divider_ena : std_logic; --=================================================================================== -- --=================================================================================== signal step_cnt_data_sload : unsigned(DATA_LENGTH - 1 downto 0); signal step_cnt : unsigned(DATA_LENGTH - 1 downto 0); signal step_cnt_is_zero : std_logic; signal step_cnt_sld_ena : std_logic; signal step_cnt_ena : std_logic; begin process(clk) begin if (rising_edge(clk)) then press_state <= next_state; if (RST = '1') then press_state <= start_work_st; end if; end if; end process; nextstate_proc : PROCESS (all) begin case press_state IS when start_work_st => next_state <= start_work_st; if (start_work = '1') then next_state <= set_pwm_0_st; end if; --=================================================================================== when set_pwm_0_st => next_state <= set_pwm_0_st; if (reg_divider_is_zero = '1') then next_state <= set_pwm_1_st; end if; if (interrupt = '1') then next_state <= stop_st; end if; --=================================================================================== when set_pwm_1_st => next_state <= set_pwm_1_st; if (reg_divider_is_zero = '1') then next_state <= set_pwm_0_st; if (step_cnt_is_zero = '1') then next_state <= stop_st; end if; end if; --=================================================================================== when stop_st => if (interrupt = '1') then next_state <= stop_st; else next_state <= start_work_st; end if; --=================================================================================== end case; end process nextstate_proc; FSM_output_logic : PROCESS (all) begin reg_divider_ena <= '0'; reg_divider_sld_ena <= '0'; ready <= '0'; pwm_out <= '0'; ready_period_shim <= '0'; step_cnt_ena <= '0'; step_cnt_sld_ena <= '0'; case press_state is when start_work_st => if (start_work = '1') then -- Пришла команда начать работу reg_divider_sld_ena <= '1'; -- Загрузим в счетчики требуемые значения step_cnt_sld_ena <= '1'; end if; --=================================================================================== when set_pwm_0_st => if (reg_divider_is_zero = '1') then -- Отсчитали полу-период нуля reg_divider_sld_ena <= '1'; -- Загрузим счетчик для отсчета полу-периода единицы end if; --=================================================================================== when set_pwm_1_st => if (reg_divider_is_zero = '1') then -- Отсчитали полу-период единицы reg_divider_sld_ena <= '1'; -- Загрузим счетчик для отсчета полу-периода нуля ready_period_shim <= '1'; -- Выдадим сигнал готовности одного периода-шим step_cnt_ena <= '1'; -- Уменьшим счетчик количества периодов. end if; pwm_out <= '1'; -- Наш шим. Это выход с регистра. Хоть это явно и не видо. --=================================================================================== when stop_st => ready <= '1'; --=================================================================================== end case; end process; --=================================================================================== -- Счетчик полу-периодов ШИМ --=================================================================================== HALF_PRD_CNT : entity work.KAA_unsigned_cnt generic map ( Direction => "Down" , Timer_mode => "Enable" , timeout_output_reg => "Enable" , Overflow => "Enable" , sclr_port => "Disable", aclr_port => "Disable", ena_port => "Disable", sld_ena_port => "Enable" , Max_value => cnt_max_value ) port map ( clk => CLK , ena => reg_divider_ena , sld_ena => reg_divider_sld_ena , data_sld => reg_divider_data_sload, timeout => reg_divider_is_zero ); reg_divider_data_sload <= unsigned(divider) - "1"; --=================================================================================== -- Счетчик периодов --=================================================================================== STEP_COUNTER : entity work.KAA_unsigned_cnt generic map ( Direction => "Down" , Timer_mode => "Enable", timeout_output_reg => "Enable", Overflow => "Enable", sclr_port => "Disable", aclr_port => "Disable", ena_port => "Enable", sld_ena_port => "Enable", Max_value => cnt_max_value ) port map ( clk => CLK , ena => step_cnt_ena , sld_ena => step_cnt_sld_ena , data_sld => step_cnt_data_sload, data_out => step_cnt , timeout => step_cnt_is_zero ); step_cnt_data_sload <= unsigned(num_step) - "1"; count_step <= std_logic_vector(step_cnt); end architecture; Я вот не понял что значит Цитата Реализация должна быть по сигналу прерывания на следующем шаге прерываться Что считать следующим шагом ? Ускорения можно достичь: 1. Если сделать счетчкики конвеерными (Вы как раз недавно делились файлами со всеми). Это кстати основной путь повышения максимальной частоты. 2. Если слегка переработать загружаемые в счетчики значения. Сейчас у меня вычитается единичка. Ибо счетчик считает от загружаемого значения до нуля. Эти значения либо где-то раньше рассчитывать. Либо счетчик должен считать от загружаемого значения до 1. Тут главное, чтобы в счетчик загрузка шла не с комбинационной логики, а с регистров. Но тут Вам решать. 3. Немного переработать граф переходов автомата. Сейчас у меня: в состоянии set_pwm_1_st проверяется является ли счетчик нулем. Если является - значит загружаем счетчики, выдаем команды и пр. Можно сделать так: загружаем в счетчик полу-периодов значение меньше на единичку (помимо того, что я уже вычел единичку). Когда счетчик досчитает до нуля. Переходим в состояние где мы загружаем новые значения в счетчики, что-то делаем и переходим состояние отсчета другого полу-периода. Но нет уверенности что это поможет. shim_fsm.zip Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 10 апреля, 2020 Опубликовано 10 апреля, 2020 · Жалоба большое спасибо Если приходит сигнал прерывание, то автомат закнчивает формирование текущего периода, но новый период не начинает формировать (на выходе PWM логический 0). Либо уходит в ожидание пока действует прерывание работы либо уходит в состояние старта (тут я еще не решил) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 10 апреля, 2020 Опубликовано 10 апреля, 2020 · Жалоба 2 минуты назад, Maverick_ сказал: большое спасибо Если приходит сигнал прерывание, то автомат закнчивает формирование текущего периода, но новый период не начинает формировать. Либо уходит в ожидание пока действует прерывание работы либо уходит в состояние старта (тут я еще не решил) Я бы слегка переработал выходные сигналы. Я бы сделал сигнал done - то, что автомат выполнил задачу. И сигнал ready - когда автомт готов получить новое задание. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 10 апреля, 2020 Опубликовано 10 апреля, 2020 · Жалоба это да. У меня (в описании которое я выложил в первом посте) сигнал ready (один такт) формируется каждого периода (ready_period_shim) и когда автомат закончил работу то формируется также ready (ready) В сигнал done можно переименовать сигнал ready - я так наверное и сделаю ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 10 апреля, 2020 Опубликовано 10 апреля, 2020 · Жалоба 1 hour ago, Flip-fl0p said: Посмотрел твои описания - мега крутые в плане понимания и документируемости... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 10 апреля, 2020 Опубликовано 10 апреля, 2020 · Жалоба 9 минут назад, Maverick_ сказал: Посмотрел твои описания - мега крутые в плане понимания и документируемости... Мой главный принцип написания кода - KISS (акроним для «Keep it simple, stupid»). чем проще написано тем лучше. Ещё я очень люблю писать FSM. Ибо ничего понятнее FSM в FPGA нет. Хотя к моему стыду KAA_unsigned_cnt надо ещё править. Я его недавно написал, и много мусора осталось. Ибо надоело держать в проекте кучу разных счетчиков. Проще описать один максимально параметризируемый. Мне кажется мне удалось. Хотя не покидает мысль попробовать описать чуть по-другому. На каждый тип счетчика описать отдельную архитектуру. Или воспользоваться блоком (никогда не пользовался ими ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 10 апреля, 2020 Опубликовано 10 апреля, 2020 · Жалоба Хороший принцип. Я к этому принципу только стремлюсь... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться