+ Post New Thread
Results 1 to 14 of 14
  1. #1
    Junior Member level 3
    Points: 493, Level: 4

    Join Date
    Jun 2016
    Posts
    29
    Helped
    0 / 0
    Points
    493
    Level
    4

    How to receive PWM and edit it ?

    In arduino so easy to receive PWM signal and edit it , and so many documentation, But in FPGA VHDL , I cannot find it .. Could someone help me to deal with it ?

    PWM coming in std_logic, and how to make it std_logic_vector and edit this ?

  2. #2
    Super Moderator
    Points: 57,471, Level: 58
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    11,705
    Helped
    2715 / 2715
    Points
    57,471
    Level
    58

    Re: How to receive PWM and edit it ?

    Hi,

    You mean PWM = pulse width modulation?

    If so, what to you mean with "receive"?
    And "edit" it in which way?

    With PWM one usually controls the speed of a DC motor, the brightness of a lamp....

    A picture and a good description could help to clarify things.

    Klaus
    Please don´t contact me via PM, because there is no time to respond to them. Thank you.



    •   Alt30th December 2017, 18:54

      advertising

        
       

  3. #3
    Junior Member level 3
    Points: 493, Level: 4

    Join Date
    Jun 2016
    Posts
    29
    Helped
    0 / 0
    Points
    493
    Level
    4

    Re: How to receive PWM and edit it ?

    Yes it is Pulse Width Modulation, for example i have output from controller is from 1000 to 2000 impulses, ie PWM impulses, but my motor can get only from 1440 to 1850 impulses, so , to adopt it I just divide PWM from Controller to 2.7 and add 1063,,, ( pwm_in / 2.7) + 1063,,..
    I have idea to convert std_logic (pwm impulses) to integer and count it , and edit it , like above and then somehow convert it to pwm output..How to convert it to std_logic again ?



  4. #4
    Super Moderator
    Points: 70,369, Level: 64
    Achievements:
    7 years registered
    Awards:
    2nd Helpful Member
    betwixt's Avatar
    Join Date
    Jul 2009
    Location
    Aberdyfi, West Wales, UK
    Posts
    11,509
    Helped
    3807 / 3807
    Points
    70,369
    Level
    64

    Re: How to receive PWM and edit it ?

    Be very careful with wording here:

    PWM implied the WIDTH of the pulses is modulated but not how frequent they are. You say the controller produces 1000 to 2000 impulses which implies it is FM (frequency modulated) not PWM.

    If you divide PWM you lose the information in the modulation because division destroys the waveform shape. Please tell us exactly what your motor expects to be driven by, for example is the PWM fed directly to a DC or AC motor or does it pass through some other circuitry first.

    Brian.
    PLEASE - no friends requests or private emails, I simply don't have time to reply to them all.
    It's better to share your questions and answers on Edaboard so we can all benefit from each others experiences.


    1 members found this post helpful.

  5. #5
    Super Moderator
    Points: 241,334, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    41,891
    Helped
    12754 / 12754
    Points
    241,334
    Level
    100

    Re: How to receive PWM and edit it ?

    I would appreciate a clearer problem description, distinguishing between PWM frequency and pulse width. "PWM impulses" is inexpressive.

    I guess you want to design a logic receiving an external PWM signal, extracting the pulse width and generating a PWM signal with manipulated pulse width and same(?) or different(?) frequency.

    The general method is setting up a timer to measure the pulse width and possibly pulse period.

    As the information represented by the pulse width is a numerical value, a straightforward VHDL approach suggests a numerical data type rather than std_logic_vector.



  6. #6
    Junior Member level 3
    Points: 493, Level: 4

    Join Date
    Jun 2016
    Posts
    29
    Helped
    0 / 0
    Points
    493
    Level
    4

    Re: How to receive PWM and edit it ?

    Dear All ,Thank you for suggestion, I spend two days to write it,because I am not good in vhdl and english,so this is working code:

    Code:
    entity pwmedit is
    	PORT(       clk100    : IN std_logic;
    			pwm_in  : IN std_logic; 
    			mult       : IN integer:=1;	
    			pwm_out: OUT std_logic);
    end pwmedit;
    
    architecture Behavioral of pwmedit is
    	signal cnt: integer:=0;
    	signal num_int: integer:=0;
    process(clk100,pwm_in)
    	begin
    		if rising_edge(clk100) 
    		   then  num_int <= num_int + 1;
    				if    pwm_in ='1'                  
    						then  num_int<=0;
    						      cnt<=cnt+1;
    						else 
    						    if num_int < (cnt+784) * mult  
    						     then pwm_out <= '1'; 
    							  else pwm_out <= '0'; cnt<=0;
    				end if; 	end if;
    		end if;										 
    end process;
    Click image for larger version. 

Name:	index.jpg 
Views:	6 
Size:	88.4 KB 
ID:	143875
    Last edited by abimann; 10th January 2018 at 16:32.



    •   Alt10th January 2018, 16:11

      advertising

        
       

  7. #7
    Super Moderator
    Points: 241,334, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    41,891
    Helped
    12754 / 12754
    Points
    241,334
    Level
    100

    Re: How to receive PWM and edit it ?

    The oscilloscope waveform suggests that the circuit generates delayed pwm pulses of same frequency. Is that what you want? If not, please give a clear specification.



  8. #8
    Junior Member level 2
    Points: 192, Level: 2

    Join Date
    Dec 2017
    Location
    Bydgoszcz - Poland
    Posts
    22
    Helped
    3 / 3
    Points
    192
    Level
    2

    Re: How to receive PWM and edit it ?

    Quote Originally Posted by abimann View Post
    Dear All ,Thank you for suggestion, I spend two days to write it,because I am not good in vhdl and english,so this is working code:

    Code:
    entity pwmedit is
    	PORT(       clk100    : IN std_logic;
    			pwm_in  : IN std_logic; 
    			mult       : IN integer:=1;	
    			pwm_out: OUT std_logic);
    end pwmedit;
    
    architecture Behavioral of pwmedit is
    	signal cnt: integer:=0;
    	signal num_int: integer:=0;
    process(clk100,pwm_in)
    	begin
    		if rising_edge(clk100) 
    		   then  num_int <= num_int + 1;
    				if    pwm_in ='1'                  
    						then  num_int<=0;
    						      cnt<=cnt+1;
    						else 
    						    if num_int < (cnt+784) * mult  
    						     then pwm_out <= '1'; 
    							  else pwm_out <= '0'; cnt<=0;
    				end if; 	end if;
    		end if;										 
    end process;
    Click image for larger version. 

Name:	index.jpg 
Views:	6 
Size:	88.4 KB 
ID:	143875
    Hello,

    in purpose to generate PWM signal (with various PWM frequency) you can use such generic VHDL module:

    Code:
    LIBRARY ieee;
    USE ieee.std_logic_1164.all;
    USE ieee.std_logic_unsigned.all;
    
    ENTITY pwm IS
      GENERIC(
          sys_clk         : INTEGER := 1_000_000; --system clock frequency in Hz
          pwm_freq        : INTEGER := 60_000;    --PWM switching frequency in Hz
          bits_resolution : INTEGER := 8;          --bits of resolution setting the duty cycle
          phases          : INTEGER := 1);         --number of output pwms and phases
      PORT(
          clk       : IN  STD_LOGIC;                                    --system clock
          reset_n   : IN  STD_LOGIC;                                    --asynchronous reset
          ena       : IN  STD_LOGIC;                                    --latches in new duty cycle
          duty      : IN  STD_LOGIC_VECTOR(bits_resolution-1 DOWNTO 0); --duty cycle
          pwm_out   : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0);          --pwm outputs
          pwm_n_out : OUT STD_LOGIC_VECTOR(phases-1 DOWNTO 0));         --pwm inverse outputs
    END pwm;
    
    ARCHITECTURE logic OF pwm IS
      CONSTANT  period     :  INTEGER := sys_clk/pwm_freq;                      --number of clocks in one pwm period
      TYPE counters IS ARRAY (0 TO phases-1) OF INTEGER RANGE 0 TO period - 1;  --data type for array of period counters
      SIGNAL  count        :  counters := (OTHERS => 0);                        --array of period counters
      SIGNAL   half_duty_new  :  INTEGER RANGE 0 TO period/2 := 0;              --number of clocks in 1/2 duty cycle
      TYPE half_duties IS ARRAY (0 TO phases-1) OF INTEGER RANGE 0 TO period/2; --data type for array of half duty values
      SIGNAL  half_duty    :  half_duties := (OTHERS => 0);                     --array of half duty values (for each phase)
    BEGIN
      PROCESS(clk, reset_n)
      BEGIN
        IF(reset_n = '0') THEN                                                 --asynchronous reset
          count <= (OTHERS => 0);                                                --clear counter
          pwm_out <= (OTHERS => '0');                                            --clear pwm outputs
          pwm_n_out <= (OTHERS => '0');                                          --clear pwm inverse outputs
        ELSIF(clk'EVENT AND clk = '1') THEN                                      --rising system clock edge
          IF(ena = '1') THEN                                                   --latch in new duty cycle
            half_duty_new <= conv_integer(duty)*period/(2**bits_resolution)/2;   --determine clocks in 1/2 duty cycle
          END IF;
          FOR i IN 0 to phases-1 LOOP                                            --create a counter for each phase
            IF(count(0) = period - 1 - i*period/phases) THEN                       --end of period reached
              count(i) <= 0;                                                         --reset counter
              half_duty(i) <= half_duty_new;                                         --set most recent duty cycle value
            ELSE                                                                   --end of period not reached
              count(i) <= count(i) + 1;                                              --increment counter
            END IF;
          END LOOP;
          FOR i IN 0 to phases-1 LOOP                                            --control outputs for each phase
            IF(count(i) = half_duty(i)) THEN                                       --phase's falling edge reached
              pwm_out(i) <= '0';                                                     --deassert the pwm output
              pwm_n_out(i) <= '1';                                                   --assert the pwm inverse output
            ELSIF(count(i) = period - half_duty(i)) THEN                           --phase's rising edge reached
              pwm_out(i) <= '1';                                                     --assert the pwm output
              pwm_n_out(i) <= '0';                                                   --deassert the pwm inverse output
            END IF;
          END LOOP;
        END IF;
      END PROCESS;
    END logic;
    This is core downloaded from opencores.org. This is generic, multi-phase and phase correct PWM generator.I am using it extensively in my project Controller for roller-blinds DC motor You can see this project at link on this forum:

    https://www.edaboard.com/showthread.php?t=373807

    The entity: WEKTORY_WYPELNIEN and WEKTORY_REVERSE are used for generating varying PWM signals (soft-starter and soft-stop for 12 V DC Motor) . This proces is fully parametrized: PWM generation (clock frequency, PWM frequency, PWM timing, number of generated PWM phases) The in PWM vectors are read from ROM simulated in VHDL array.

    If you want I can send you more code of this project -with some explanation (sorry for Polish comments in VHDL code ).

    Regards
    Last edited by FlyingDutch; 10th January 2018 at 17:01.



  9. #9
    Junior Member level 3
    Points: 493, Level: 4

    Join Date
    Jun 2016
    Posts
    29
    Helped
    0 / 0
    Points
    493
    Level
    4

    Re: How to receive PWM and edit it ?

    pls send me to XXXXXXXXXX, is there tachometer also used to correct some speed or hertz or rpm ??
    Last edited by KlausST; 11th January 2018 at 06:57. Reason: Removing eMail address



  10. #10
    Junior Member level 2
    Points: 192, Level: 2

    Join Date
    Dec 2017
    Location
    Bydgoszcz - Poland
    Posts
    22
    Helped
    3 / 3
    Points
    192
    Level
    2

    Re: How to receive PWM and edit it ?

    Quote Originally Posted by abimann View Post
    pls send me to XXXXXXXXXX, is there tachometer also used to correct some speed or hertz or rpm ??

    Hello,

    no I don't use tachometer (or any sensor for measuring speed of DC Motor) I just needen't it. I am afraid that you choose bad atitiude for your problem.

    Could you describe how parameters has input PWM signal ?

    1) PWM frequency
    2) How many bits resolution (for example : 8 bit PWM - the period is divided to 255 intervals)
    3) I assumed that you have only one phase PWM signal

    And after that what device you wanna to steer (output PWM signal). How the input PWM signal have to be processed to generate output PWM signal ?

    What is final purpose of output PWM (what device it would be steering by tha signal)?

    Your post is in many aspects unclear. Could you clarify it a bit ? I can send you all code of my project, but I am not sure if it will be useful for your needs?

    BTW: I guess that you want to stabilize the speed (rpms) of DC motor using PWM signal ? In such case you have to use motors encoders (for measuring speed). Output of this encoder should be input signal to "PID Regulator" and output form PID regulator (error signal) should alter the process of generating PWM signal. This is much more complicated design, but can be achived by using that generic PWM generator (wchich code I attached). Of course you have to write much additional code by yourself. There are PID regulator free IP cores available on the net.

    Regards
    Last edited by FlyingDutch; 11th January 2018 at 09:50.



    •   Alt11th January 2018, 09:35

      advertising

        
       

  11. #11
    Junior Member level 3
    Points: 493, Level: 4

    Join Date
    Jun 2016
    Posts
    29
    Helped
    0 / 0
    Points
    493
    Level
    4

    Re: How to receive PWM and edit it ?

    There are no any fixed data needed, just it need to modify incoming pwm signal from flight controller and send it out to motor and regulate motor speed by getting hertz or revolution per 20ms .. So problem is solved , by myself and i want if someone need this he can use above code,because googling dont give me result..and no one write this kind of code.



  12. #12
    Junior Member level 2
    Points: 192, Level: 2

    Join Date
    Dec 2017
    Location
    Bydgoszcz - Poland
    Posts
    22
    Helped
    3 / 3
    Points
    192
    Level
    2

    Re: How to receive PWM and edit it ?

    Quote Originally Posted by abimann View Post
    There are no any fixed data needed, just it need to modify incoming pwm signal from flight controller and send it out to motor and regulate motor speed by getting hertz or revolution per 20ms .. So problem is solved , by myself and i want if someone need this he can use above code,because googling dont give me result..and no one write this kind of code.
    Hello abinam,

    maybe I am not clever ehough to understand what problem you have.

    So problem is solved , by myself and i want if someone need this he can use above code,because googling dont give me result..and no one write this kind of code.
    Your code has serious issues, and do nothing (what I demonstrate in simulation).

    First issue:

    Code:
    entity pwmedit is
    	PORT(       clk100    : IN std_logic;
    			pwm_in  : IN std_logic; 
    			mult       : IN integer:=1;	
    			pwm_out: OUT std_logic);
    end pwmedit;
    You are using integer as input signal to your entity: mult : IN integer:=1;
    Are you aware what are you doing?

    The integer is treated as 32-bit vector what causing that multiplaying by 1 is taking huge amount of LUTs (* operator is very non effective as general).

    See link:

    https://forums.xilinx.com/t5/Welcome...ts/td-p/284364

    You should use GENERIC construct in entity of pwmedit:

    Code:
    entity pwmedit is
       generic ( mult : integer := 1);  -- multiplayer
    	PORT( clk100    : IN std_logic;
    			pwm_in  : IN std_logic; 
    			pwm_out: OUT std_logic);
    end pwmedit;
    Wthout that changes you wouldn't be able to make simulation of your code (test-bench). Your project without that change occupy about 700 LUTs (my much bigger project takes less). After changes your code looks like that:

    Code:
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    
    entity pwmedit is
       generic ( mult : integer := 1);  -- multiplayer
    	PORT( clk100    : IN std_logic;
    			pwm_in  : IN std_logic; 
    			pwm_out: OUT std_logic);
    end pwmedit;
    
    architecture Behavioral of pwmedit is
    	signal cnt: integer :=0;
    	signal num_int: integer :=0;
    begin	
    
    process(clk100,pwm_in)
    	begin
    		if rising_edge(clk100) 
    		   then  
    			   num_int <= num_int + 1;
    				if  (pwm_in = '1')                  
    						then  
    						  num_int<=0;
    						  cnt<=cnt+1;
    						else 
    						    if (num_int < ((cnt+784) * mult))  
    						     then pwm_out <= '1'; 
    							  else pwm_out <= '0'; cnt<=0;
    				end if; 	end if;
    		end if;										 
    end process;
    
    end Behavioral;
    I made a test bench for this code and try to simulate it (I was changing pwm_in signal with various period and pwm_out was staing unchanged). This is code of test bench for your entity:

    Code:
    LIBRARY ieee;
    USE ieee.std_logic_1164.ALL;
     
    -- Uncomment the following library declaration if using
    -- arithmetic functions with Signed or Unsigned values
    --USE ieee.numeric_std.ALL;
     
    ENTITY pwmedit_TB IS
    END pwmedit_TB;
     
    ARCHITECTURE behavior OF pwmedit_TB IS 
     
        -- Component Declaration for the Unit Under Test (UUT)
     
        COMPONENT pwmedit
    	 generic ( mult : integer := 1);  -- multiplayer
        PORT(
             clk100 : IN  std_logic;
             pwm_in : IN  std_logic;
             pwm_out : OUT  std_logic
            );
        END COMPONENT;
        
    
       --Inputs
       signal clk100 : std_logic := '0';
       signal pwm_in : std_logic := '0';
    
     	--Outputs
       signal pwm_out : std_logic;
    
       -- Clock period definitions
       constant clk100_period : time := 100 ns;
     
    BEGIN
     
    	-- Instantiate the Unit Under Test (UUT)
       uut: pwmedit PORT MAP (
              clk100 => clk100,
              pwm_in => pwm_in,
              pwm_out => pwm_out
            );
    
       -- Clock process definitions
       clk100_process :process
       begin
    		clk100 <= '0';
    		wait for clk100_period/2;
    		clk100 <= '1';
    		wait for clk100_period/2;
       end process;
     
    
       -- Stimulus process
       stim_proc: process
       begin		
          -- hold reset state for 100 ns.
          wait for 100 ns;	
    
          wait for clk100_period*10;
    
          -- insert stimulus here 
    			pwm_in <= '1';
    		wait for clk100_period*100;
    		
    		pwm_in <= '0';
    		wait for clk100_period*100;
    		
    		pwm_in <= '1';
    		wait for clk100_period*100;
    		
    		pwm_in <= '0';
    		wait for clk100_period*100;
    		
    		pwm_in <= '1';
    		wait for clk100_period*400;
    		
    		pwm_in <= '0';
    		wait for clk100_period*400;
    		
    		pwm_in <= '1';
    		wait for clk100_period*1000;
    		
    		pwm_in <= '0';
    		wait for clk100_period*1000;
    		
    		pwm_in <= '1';
    		wait for clk100_period*4000;
    		
    		pwm_in <= '0';
    		wait for clk100_period*4000;
    		
    		pwm_in <= '1';
    		wait for clk100_period*4000;
    		
    		pwm_in <= '0';
    		wait for clk100_period*4000;
    		
    
          wait;
       end process;
    
    END;
    And here you can see results of simulation:

    - - - Updated - - -

    This is last part of my last answer:

    Result of simulation:

    Click image for larger version. 

Name:	ISIM_PWM.PNG 
Views:	10 
Size:	105.2 KB 
ID:	143911

    Maybe when coincedence of some clock frequency and incoming PWM signal frequency took place your code is doing something, you need.

    Why do you think that someone wanna to use your buggy code - what purpose is unclear ?

    Regards
    Last edited by FlyingDutch; 12th January 2018 at 11:42.



  13. #13
    Junior Member level 2
    Points: 192, Level: 2

    Join Date
    Dec 2017
    Location
    Bydgoszcz - Poland
    Posts
    22
    Helped
    3 / 3
    Points
    192
    Level
    2

    Re: How to receive PWM and edit it ?

    BTW: If you using integer as input ports, you should at least apply range to it:

    Code:
    entity pwmedit is
    	PORT(       clk100    : IN std_logic;
    			pwm_in  : IN std_logic; 
    			mult       : IN integer:=1;	
    			pwm_out: OUT std_logic);
    end pwmedit;
    in order to economize resources using in FPGA, but still it is bad habit in design.

    Regards


    1 members found this post helpful.

  14. #14
    Junior Member level 3
    Points: 493, Level: 4

    Join Date
    Jun 2016
    Posts
    29
    Helped
    0 / 0
    Points
    493
    Level
    4

    Re: How to receive PWM and edit it ?

    This code working , I don't know how to make simulation, i am sure smth wrong with your simulation code..but i check it in real hardware and oscilloscope..I cannot find any other vhdl code which is reads PWM in , so...



--[[ ]]--