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

Как прикрутить к VHDL коду ШИМ настроечный вход?

Доброго всем времени суток!...

Прошу помощи, мне требовалось сделать ШИМ с настройкой периода и частоты, при этом сейчас появилась необходимость добавить к уже имеющемуся коду настроечный вход типа "ПИЛЫ". Для 1 должна быть пила, а для 0 обратная пила.

Я даже теоретически не представляю себе как его сделать. Помогите пожалуйста дописать к уже имеющемуся коду данную настройку. Исходный код выложу ниже. Спасибо.

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY pwm IS
  GENERIC(
      sys_clk         : INTEGER := 50_000_000; 
      pwm_freq        : INTEGER := 100_000;    
      bits_resolution : INTEGER := 8;         
      phases          : INTEGER := 1);         
  PORT(
      clk       : IN  STD_LOGIC;                                   
      reset_n   : IN  STD_LOGIC;                                   
      ena       : IN  STD_LOGIC;                                    
      duty      : IN  STD_LOGIC_VECTOR(bits_resolution-1 DOWNTO 0); 
      pwm_out   : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0);          
      pwm_n_out : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0));         
END pwm;

ARCHITECTURE logic OF pwm IS
  CONSTANT period  : INTEGER := sys_clk/pwm_freq;                         
  TYPE counters IS ARRAY (0 TO phases-1) OF INTEGER RANGE 0 TO period - 1; 
  SIGNAL count     : counters := (OTHERS => 0);                            
  SIGNAL half_duty : INTEGER RANGE 0 TO period/2 := 0;                    
BEGIN
  PROCESS(clk, reset_n)
  BEGIN
    IF(reset_n = '0') THEN                                             
      count <= (OTHERS => 0);                                            
      pwm_out <= (OTHERS => '0');                                        
      pwm_n_out <= (OTHERS => '0');                                      
    ELSIF(clk'EVENT AND clk = '1') THEN                                
      IF(ena = '1') THEN                                                 
        half_duty <= conv_integer(duty)*period/(2**bits_resolution)/2;     
      END IF;
      FOR i IN 0 to phases-1 LOOP                                       
        IF(count(0) = period - 1 - i*period/phases) THEN                  
          count(i) <= 0;                                                     
        ELSE                                                               
          count(i) <= count(i) + 1;                                          
        END IF;
      END LOOP;
      FOR i IN 0 to phases-1 LOOP                                  
        IF(count(i) = half_duty) THEN                                      
          pwm_out(i) <= '0';                                               
          pwm_n_out(i) <= '1';                                             
        ELSIF(count(i) = period - half_duty) THEN                          
          pwm_out(i) <= '1';                                                
          pwm_n_out(i) <= '0';                                             
        END IF;
      END LOOP;
    END IF;
  END PROCESS;
END logic;

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


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

не надо трогать этот модуль

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

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


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

не надо трогать этот модуль

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

Спасибо!...А как это сделать не подскажите?

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


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

давно на VHDL не писал... так что пас...

 

я чет даже не помню как в нем модули объявляются... попробовал но ничего хорошего не выйдет...

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


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

Спасибо!...А как это сделать не подскажите?

поробуйте "поиграться" с

...
count(i) <= count(i) + 1;
...

 

+ поменять на -

и посмотрите что будет...

 

для управления

можно написать что-то в таком духе:

...
if sel = "1" then 
count(i) <= count(i) + 1;
else
count(i) <= count(i) - 1;
end if;
...

 

и не забудьте добавить sel в декларацию сигналов/порта выхода

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


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

Спасибо!...А как это сделать не подскажите?

 

Примерно так, если я верно понял, что нужно:

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY pwm_sawtooth IS
     GENERIC(
         sys_clk         : INTEGER := 50_000_000;
         pwm_freq        : INTEGER := 100_000;
         bits_resolution : INTEGER := 8;
         phases          : INTEGER := 1
     );        
     PORT(
         clk       : IN  STD_LOGIC;
         reset_n   : IN  STD_LOGIC;
         ena       : IN  STD_LOGIC;
         pwm_out   : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0);
         pwm_n_out : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0);
         
         direction : IN  STD_LOGIC -- set sawtooth direction: 0 - rising, 1 - falling
     );
END pwm_sawtooth;

ARCHITECTURE logic OF pwm_sawtooth IS
     
     -- Components used in the design
     COMPONENT pwm
         GENERIC(
             sys_clk         : INTEGER := 50_000_000;
             pwm_freq        : INTEGER := 100_000;
             bits_resolution : INTEGER := 8;
             phases          : INTEGER := 1
         );
         PORT(
             clk       : IN  STD_LOGIC;
             reset_n   : IN  STD_LOGIC;
             ena       : IN  STD_LOGIC;
             duty      : IN  STD_LOGIC_VECTOR(bits_resolution-1 DOWNTO 0);
             pwm_out   : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0);
             pwm_n_out : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0)
         );
     END COMPONENT;

     -- Entity variables
     SIGNAL duty: STD_LOGIC_VECTOR(bits_resolution-1 DOWNTO 0);
BEGIN

     -- PWM module connection
     pwm_cmp: pwm GENERIC MAP(
             sys_clk => sys_clk,
             pwm_freq => pwm_freq,
             bits_resolution => bits_resolution,
             phases => phases
         )
         PORT MAP(
             clk => clk,
             reset_n => reset_n,
             ena => ena,
             duty => duty,
             pwm_out => pwm_out,
             pwm_n_out => pwm_n_out
         );

     -- Sawtooth counter
     PROCESS(clk, reset_n)
     BEGIN
         IF(reset_n = '0') THEN
             duty <= (OTHERS => '0');
         ELSIF(rising_edge(clk)) THEN
             IF(direction = '0') THEN duty <= duty + '1';
             ELSE duty <= duty - '1';
             END IF;
         END IF;
     END PROCESS;

END logic;

 

А вот тестбенч (на верилоге для простоты):

// Testbench for PWM_SAWTOOTH module

module pwm_sawtooth_tb;

     reg clk, reset_n;
     
     wire ena = 1'b1;
     
     reg direction;
     
     initial begin
         clk = 1'b0;
         reset_n = 1'b0;
         direction = 1'b0;
         
         #1 reset_n = 1'b1;
         
         
         #1000 direction = 1'b1;
     end

     pwm_sawtooth DUT (
                 .clk,
                 .reset_n,
                 .ena,
                 //pwm_out   : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0);
                 //pwm_n_out : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0);

                 .direction
         );

endmodule // pwm_sawtooth_tb

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


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

Примерно так, если я верно понял, что нужно:

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY pwm_sawtooth IS
     GENERIC(
         sys_clk         : INTEGER := 50_000_000;
         pwm_freq        : INTEGER := 100_000;
         bits_resolution : INTEGER := 8;
         phases          : INTEGER := 1
     );        
     PORT(
         clk       : IN  STD_LOGIC;
         reset_n   : IN  STD_LOGIC;
         ena       : IN  STD_LOGIC;
         pwm_out   : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0);
         pwm_n_out : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0);
         
         direction : IN  STD_LOGIC -- set sawtooth direction: 0 - rising, 1 - falling
     );
END pwm_sawtooth;

ARCHITECTURE logic OF pwm_sawtooth IS
     
     -- Components used in the design
     COMPONENT pwm
         GENERIC(
             sys_clk         : INTEGER := 50_000_000;
             pwm_freq        : INTEGER := 100_000;
             bits_resolution : INTEGER := 8;
             phases          : INTEGER := 1
         );
         PORT(
             clk       : IN  STD_LOGIC;
             reset_n   : IN  STD_LOGIC;
             ena       : IN  STD_LOGIC;
             duty      : IN  STD_LOGIC_VECTOR(bits_resolution-1 DOWNTO 0);
             pwm_out   : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0);
             pwm_n_out : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0)
         );
     END COMPONENT;

     -- Entity variables
     SIGNAL duty: STD_LOGIC_VECTOR(bits_resolution-1 DOWNTO 0);
BEGIN

     -- PWM module connection
     pwm_cmp: pwm GENERIC MAP(
             sys_clk => sys_clk,
             pwm_freq => pwm_freq,
             bits_resolution => bits_resolution,
             phases => phases
         )
         PORT MAP(
             clk => clk,
             reset_n => reset_n,
             ena => ena,
             duty => duty,
             pwm_out => pwm_out,
             pwm_n_out => pwm_n_out
         );

     -- Sawtooth counter
     PROCESS(clk, reset_n)
     BEGIN
         IF(reset_n = '0') THEN
             duty <= (OTHERS => '0');
         ELSIF(rising_edge(clk)) THEN
             IF(direction = '0') THEN duty <= duty + '1';
             ELSE duty <= duty - '1';
             END IF;
         END IF;
     END PROCESS;

END logic;

 

А вот тестбенч (на верилоге для простоты):

// Testbench for PWM_SAWTOOTH module

module pwm_sawtooth_tb;

     reg clk, reset_n;
     
     wire ena = 1'b1;
     
     reg direction;
     
     initial begin
         clk = 1'b0;
         reset_n = 1'b0;
         direction = 1'b0;
         
         #1 reset_n = 1'b1;
         
         
         #1000 direction = 1'b1;
     end

     pwm_sawtooth DUT (
                 .clk,
                 .reset_n,
                 .ena,
                 //pwm_out   : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0);
                 //pwm_n_out : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0);

                 .direction
         );

endmodule // pwm_sawtooth_tb

Ваше описание задает изменение длительности ШИМ (соотношение 1 и 0 в периоде)

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


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

Ваше описание задает изменение длительности ШИМ (соотношение 1 и 0 в периоде)

evgoi ведь того и хотел ?

появилась необходимость добавить к уже имеющемуся коду настроечный вход типа "ПИЛЫ". Для 1 должна быть пила, а для 0 обратная пила.

Или ... ?

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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