0

How to generate a PWM signal using an FPGA? Which is best method to generate a variable duty cycle?

I tried to solve this problem by using the following code but two or three errors occurred.

This is my code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

use ieee.numeric_std.all;
--use ieee.float_pkg.all;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.

--library UNISIM;
--use UNISIM.VComponents.all;

entity pwm_sne is
  Generic(
    sys_clk         :integer :=50000000;
    pwm_freq        :integer :=100000;
    bits_resolution :integer :=8
  );
  Port (
    clk : in  STD_LOGIC;
    rst : in  STD_LOGIC;
    k   : in  STD_LOGIC_VECTOR (7 downto 0);
    y   : out STD_LOGIC
  );
end pwm_sne;

architecture Behavioral of pwm_sne is
  signal cnt      :std_logic_vector(7 downto 0);
  signal flag     :std_logic;
  signal reg      :std_logic_vector(7 downto 0);
  --variable duty   :std_logic:=0;
begin
  process(clk,rst)
  begin
    if rst='1' then
      cnt<="00000000";
    elsif(clk'event and clk='1')then
      cnt<=cnt+"00000001";
    elsif cnt="11111111" then
      flag<='0';
      cnt<="00000000";
    end if;
  end process;

  process(clk,flag)
  begin
    if(clk'event and clk='1') then
      reg<=k;
    end if;
  end process;

  process(cnt,reg)
  begin
    if(flag='0')then
    elsif cnt>reg then
      y<=(reg/256)*100;
      --y<=duty;
    elsif cnt=reg then
      y<=(reg/256)*100;
    elsif cnt<=reg then
      y<=period;
      --y<=duty;
    end if;
  end process;
end Behavioral;

The errors occurred in output value y and at the division operation.

Please suggest a good method to solve the problems from above.

2
  • 1
    Welcome to Stack Overflow. You could help those trying to answer your question: How about adding your testbench code? see MCVE How about being more specific about exactly what errors you have. What is happening? What did you expect to happen? Having said that, this doesn't look right: elsif cnt="11111111" then. Are you sure it shouldn't be if cnt="11111111" then ? (If so, you'll need an extra end if; ). Commented Mar 18, 2016 at 11:48
  • 1
    What are the error messages? Commented Mar 18, 2016 at 12:17

1 Answer 1

0

Solution : Do maths on numbers, not on untyped bags of bits.

If cnt, reg,k were natural range 0 to 255 and you compared cnt with 0 or 255 and added 1 to it, this would just work. And if k MUST be std_logic_vector, use ONE type conversion function between it and reg.

Also recommended : delete the non-standard std_logic_arith andstd_logic_unsignedlibs and usenumeric_std` instead.

Sign up to request clarification or add additional context in comments.

2 Comments

Also assigning std_logic y the result of multiplying operators (e.g. y<=(reg/256)*100;) , period not declared.
Well the likely reason for "Period not declared" is pretty obvious. And there is no known multiplication operator that returns a single bit (std_logic) so that's obvious too. What's not so obvious is what you are trying to do with that line of code : figure that out and actually implementing it will be easy. But a normal PWM controller would put out either '0' or '1' on Y.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.