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

проблемы с PWM

Всем доброго дня :)

Под конец рабочего дня ... голова не "варит"

Реализация должна быть по сигналу прерывания на следующем шаге прерываться. Делать строго заданное количество шагов(периодов) (num_step в тестбенче).

Можно ли ускорить работу  (тактовую частоту) или/и упростить логику? Как по мне описание немного сложноватое...

 

shim_fsm.rar

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


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

10 минут назад, Maverick_ сказал:

Всем доброго дня :)

Под конец рабочего дня ... голова не "варит"

Реализация должна быть по сигналу прерывания на следующем шаге прерываться. Делать строго заданное количество шагов(периодов) (num_step в тестбенче).

Можно ли ускорить работу  (тактовую частоту) или/и упростить логику? Как по мне описание немного сложноватое...

 

shim_fsm.rar

А для какого чипа делается ? Я сейчас собаку выгуляю и могу глянуть проект. 

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


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

1 minute ago, Flip-fl0p said:

А для какого чипа делается ? Я сейчас собаку выгуляю и могу глянуть проект. 

Zynq / CycloneV SoC

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


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

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

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


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

большое спасибо

Если приходит сигнал прерывание, то автомат закнчивает формирование текущего периода, но новый период не начинает формировать (на выходе PWM логический 0).

Либо уходит в ожидание пока действует прерывание работы либо уходит в состояние старта (тут я еще не решил)

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


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

2 минуты назад, Maverick_ сказал:

большое спасибо

Если приходит сигнал прерывание, то автомат закнчивает формирование текущего периода, но новый период не начинает формировать.

Либо уходит в ожидание пока действует прерывание работы либо уходит в состояние старта (тут я еще не решил)

Я бы слегка переработал выходные сигналы. Я бы сделал сигнал done - то, что автомат выполнил задачу. И сигнал ready - когда автомт готов получить новое задание.

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


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

это да.

У меня (в описании которое я выложил в первом посте) сигнал ready  (один такт) формируется каждого периода (ready_period_shim) и когда автомат закончил работу то формируется также ready (ready)

В сигнал done можно переименовать сигнал ready - я так наверное и сделаю ...

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


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

1 hour ago, Flip-fl0p said:

 

Посмотрел твои описания - мега крутые в плане понимания и документируемости...

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


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

9 минут назад, Maverick_ сказал:

Посмотрел твои описания - мега крутые в плане понимания и документируемости...

Мой главный принцип написания кода - KISS (акроним для «Keep it simple, stupid»).  чем проще написано тем лучше. Ещё я очень люблю писать FSM.  Ибо ничего понятнее FSM в FPGA нет.

Хотя к моему стыду KAA_unsigned_cnt надо ещё править. Я его недавно написал, и много мусора осталось. Ибо надоело держать в проекте кучу разных счетчиков. Проще описать один максимально параметризируемый. Мне кажется мне удалось. Хотя не покидает мысль попробовать описать чуть по-другому. На каждый тип счетчика описать отдельную архитектуру. Или воспользоваться блоком (никогда не пользовался ими )

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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