Very fast PWM in Cyclone III FPGA

S

Steffen Koepf

Guest
Hello,

i need a very fast PWM in a Cyclone III FPGA.
If necessary, a Cyclone IV will do it too.

I need a 80 KHz PWM for direct Gate Control in a Switchmode Power Supply.

At the moment the Cyclone III is running at 400 MHz, which gives at 80 KHz
5000 Steps. I made it to be able to use the falling edge in my PWM-
Comparator, too, so i have now 10000 Steps at 80 KHz.

But the resolution is still not enough, i would like to have more steps.

Using a -6 speed grade Cyclone III would allow 600 MHz, which gives around
15000 Steps.

Does one know a way to get even more?
Is there a way to use the SERDES LVDS to get a fast PWM?

Is it possible to use the PLL to generate higher frequencies and use them
for example by ANDing them for 4 sub-steps (two more bits)?


Thanks in advance,

Steffen
 
On Apr 28, 8:52 pm, Steffen Koepf <Taxman-use...@opaya.de> wrote:
Hello,

i need a very fast PWM in a Cyclone III FPGA.
If necessary, a Cyclone IV will do it too.

I need a 80 KHz PWM for direct Gate Control in a Switchmode Power Supply.

At the moment the Cyclone III is running at 400 MHz, which gives at 80 KHz
5000 Steps. I made it to be able to use the falling edge in my PWM-
Comparator, too, so i have now 10000 Steps at 80 KHz.

Why don't you use a NCO? you can have resolution under 1Hz


But the resolution is still not enough, i would like to have more steps.

Using a -6 speed grade Cyclone III would allow 600 MHz, which gives around
15000 Steps.

Does one know a way to get even more?
Is there a way to use the SERDES LVDS to get a fast PWM?

Is it possible to use the PLL to generate higher frequencies and use them
for example by ANDing them for 4 sub-steps (two more bits)?

Thanks in advance,

Steffen
 
In article <ipcd0iUs98L1@news.in-ulm.de>, Steffen Koepf
<Taxman-usenet@opaya.de> wrote:

Hello,

i need a very fast PWM in a Cyclone III FPGA.
If necessary, a Cyclone IV will do it too.

I need a 80 KHz PWM for direct Gate Control in a Switchmode Power Supply.

At the moment the Cyclone III is running at 400 MHz, which gives at 80 KHz
5000 Steps. I made it to be able to use the falling edge in my PWM-
Comparator, too, so i have now 10000 Steps at 80 KHz.

But the resolution is still not enough, i would like to have more steps.

Using a -6 speed grade Cyclone III would allow 600 MHz, which gives around
15000 Steps.

Does one know a way to get even more?
If you need a value of e.g. 3128.357/5000 out of your PWM, then make
your pulse width either 3129 (35.7% of the time) or 3128 (64.3% of the
time).

If necessary for your application, apply randomness cleverly enough
that you don't get significant subharmonics (undertones) of the 80 kHz.


Is there a way to use the SERDES LVDS to get a fast PWM?

Is it possible to use the PLL to generate higher frequencies and use them
for example by ANDing them for 4 sub-steps (two more bits)?


Thanks in advance,

Steffen
--
David M. Palmer dmpalmer@email.com (formerly @clark.net, @ematic.com)
 
On Apr 28, 9:52 pm, Steffen Koepf <Taxman-use...@opaya.de> wrote:
I need a 80 KHz PWM for direct Gate Control in a Switchmode Power Supply.

At the moment the Cyclone III is running at 400 MHz, which gives at 80 KHz
5000 Steps. I made it to be able to use the falling edge in my PWM-
Comparator, too, so i have now 10000 Steps at 80 KHz.
Here is an example of PWM generator with sub-cycle (average) accuracy:

input_max is the resolution of pwm you want.
count_num defines the pwm frequency.

Does it fit to your needs?

- Topi

********
library ieee;
use ieee.std_logic_1164.all;

entity pwm_gen_fast is
generic(
input_max: integer := 1e6; -- PWM input range max value.
count_num: integer := 100e6/80e3 -- number of clk cycles of one PWM
cycle.
);
port(
clk_in: in std_logic;
pwm_in: in integer range 0 to input_max;
pwm_out: out std_logic
);
end;

architecture synth of pwm_gen_fast is
constant rat_val: integer := (input_max)/(count_num);
signal store: integer range 0 to input_max := 0;
signal counter: integer range 0 to count_num-1 := 0;
signal pwm: std_logic;
begin
process(clk_in)
variable new_store: integer range 0 to input_max+rat_val := 0;
variable rst_counter: boolean;
variable new_pwm: std_logic;
variable new_counter : integer;
begin
if rising_edge(clk_in) then
rst_counter := false;
new_pwm := pwm;

new_store := store;
if new_store < pwm_in then
new_store := new_store + rat_val;
end if;

if counter = count_num-1 then
new_counter := 0;
rst_counter := true;
else
new_counter := counter + 1;
end if;

if rst_counter then
new_store := new_store - pwm_in;
store <= new_store;
end if;

if new_counter = 0 then
new_pwm := '1';
end if;
if new_store >= pwm_in then
new_pwm := '0';
end if;

pwm <= new_pwm;
counter <= new_counter;
store <= new_store;
end if;
end process;

pwm_out <= pwm;
end;

library ieee;
use ieee.std_logic_1164.all;

entity tb_pwm_gen_fast is
end;

architecture tb of tb_pwm_gen_fast is
signal clk: std_logic;
signal pwm_in: integer range 0 to 100 := 0;
signal pwm_out: std_logic;
begin
DUT: entity work.pwm_gen_fast
generic map(
input_max => 100,
count_num => 10
)
port map(
clk_in => clk,
pwm_in => pwm_in,
pwm_out => pwm_out
);

process
begin
clk <= '0';
wait for 500 ns;
clk <= '1';
wait for 500 ns;
end process;

process
begin
pwm_in <= 1;
wait for 5000 us;
pwm_in <= 80;
wait for 1000 us;
pwm_in <= 82;
wait for 1000 us;
pwm_in <= 100;
wait for 1000 us;
pwm_in <= 99;
wait for 1000 us;
assert false report "all done" severity failure;
wait;
end process;
end;
********
 

Welcome to EDABoard.com

Sponsor

Back
Top