EmbDev.net

Forum: FPGA, VHDL & Verilog Increasing dutycycle for an output signal


Author: Robert (Guest)
Posted on:

Rate this post
0 useful
not useful
Hi all,

I want to increase the duty cycle slowly from 0%-50% in the period of 
0-10 ms for an output signal(150KHz) generated from a clock of 50MHz.

I am able to generate the output for 50%. I am not sure how to vary the 
duty cycle from 0-50% (between 0-10ms). Below is the code:
entity Gen_150 is
port ( sys_clk,reset: in std_logic; --sys_clk:50MHz
a_out, b_out: out std_logic);       --a_out,b_out:150KHz
end Gen_150 ;
 
architecture bhv of Gen_150 is
 
signal count: integer:=0;
signal tmp : std_logic := '1';

begin
 
process(sys_clk,reset)
begin
if(reset='0') then
count<=0;
tmp<='1';
elsif(sys_clk'event and sys_clk='1') then
  count <=count+1;

  if (count = 166) then   -- dutycycle=50% ((50000000/150000)/2)
     tmp <= NOT tmp;
     count<= 0;  
  end if;
end if;
a_out <= tmp;
b_out <= NOT tmp after 10ns; -- output delayed by 10ns
end process;
 
end bhv;

Thank you!

Author: Duke Scarring (Guest)
Posted on:

Rate this post
0 useful
not useful
You need another 'signal' generator (triangle wave, 100Hz) and connect 
it with your comparator:

Robert wrote:
> if (count = 166) then

Constantly changing (slowly) your compare value (166), should do it.

Duke

Author: Okay (Guest)
Posted on:

Rate this post
0 useful
not useful
Why not compare count to another register you can dynamically set in the 
process instead of a constant?

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Robert wrote:
> Below is the code:
> entity Gen_150 is
A VHDL code start well before the keyword "entity"...


> b_out <= NOT tmp after 10ns; -- output delayed by 10ns
Thats not synthesizeable! You know that?


> I want to increase the duty cycle slowly from 0%-50%
Try that and change the value of pwm:
signal count: integer:=0;
signal pwm: integer:=100;
:
:
elsif(sys_clk'event and sys_clk='1') then
  count <=count+1;

  if (count = 332) then
     count <= 0;  
  end if;
   
end if;

tmp <= '1' when (count < pwm) else '0';
:
:
end process;
Now you have a changing output signal. And the only thing you must du, 
is to produce a ramp on the "pwm" signal. Thats fairly easy...

Author: Robert (Guest)
Posted on:

Rate this post
0 useful
not useful
Thank you!
I implemented the ramping function with a counter=500000 (0-10ms). 
Please correct if I am wrong.

And I am getting an syntax error for the below:

tmp <= '1' when(count < pwm) else tmp <= '0';
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
 
entity Gen_150 is
port ( sys_clk,reset: in std_logic;
a_out, b_out: out std_logic);
end Gen_150 ;
 
architecture bhv of Gen_150 is
 
signal count: integer:=0;
signal tmp : std_logic := '1';
signal counter: integer := 0;
signal pwm: integer := 0;

begin
 
process(sys_clk,reset)
begin
if(reset='0') then
count<=0;
tmp<='1';
elsif(sys_clk'event and sys_clk='1') then
  count <=count+1;
  --counter <= counter +1;
  if (count = 332) then
    -- tmp <= NOT tmp;
     count<= 0;  
  end if;
end if;
tmp <= '1' when(count < pwm) else tmp <= '0'; 

a_out <= tmp;
b_out <= NOT tmp;

end process;

Ramp : process (reset, sys_clk)
begin
  if reset = '0' then
    pwm      <= 0;
  elsif rising_edge(sys_clk)  then
    counter <= counter +1;
    if counter<=500000 then -- 500000 cycles =10ms
      
        case  counter  is
          when  50000     =>  pwm  <= 25;    
          when  100000  =>  pwm  <= 33;  
          when  150000  =>  pwm  <= 44;  
          when  200000  =>  pwm  <= 66;  
          when  250000  =>  pwm  <= 77;  
          when  300000  =>  pwm  <= 99;            
          when  350000  =>  pwm  <= 120;  
          when  400000  =>  pwm  <= 132;  
          when  450000  =>  pwm  <= 145;  
          when  500000  =>  pwm  <= 166;  
          
          when  others  =>  pwm  <= 0;    
        end case;
      
    else
      pwm      <= 0;
    end if;
  end if;

end process Ramp;
 
end bhv;

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Robert wrote:
> And I am getting an syntax error for the below:
>
> tmp <= '1' when(count < pwm) else tmp <= '0';
Of course you do. What's the correct syntax for the when/else statement?
Why didn't you simply copy it from me?
Mine will not conclude in an error message.

And for the PWM value: let start it from 0. And then increment it every 
500000/166 clocks. So you will only need an additional counter from 0 to 
500000/166. And when the counter reaches that value you must reset it to 
0 and increment the PWM value until its 166.

You see that there's no whatsoever "case" statement necessary at all and 
the PWM value will increase smoothly from 0 to 166...

: Edited by Moderator
Author: Robert (Guest)
Posted on:

Rate this post
0 useful
not useful
Lothar M. wrote:
> Robert wrote:
>> And I am getting an syntax error for the below:
>>
>> tmp <= '1' when(count < pwm) else tmp <= '0';
> Of course you do. What's the correct syntax for the when/else statement?
> Why didn't you simply copy it from me?
> Mine will not conclude in an error message.

Sorry it was my mistake. Its fine now. But is the ramp function 
implemented correct?

Author: Robert (Guest)
Posted on:

Rate this post
0 useful
not useful
Thanks a ton! It works fine. :)

Author: Duke Scarring (Guest)
Posted on:

Rate this post
0 useful
not useful
Robert wrote:
> But is the ramp function
> implemented correct?
That's usually checked by a testbench...

Author: Robert (Guest)
Posted on:

Rate this post
0 useful
not useful
I want to add delays between the outputs (a_out and b_out).

Is it ok to add a min delay(is 10ns too much?) just by adding a temp 
register to delay out_b?
if(reset='0') then
count<=0;
tmp<='1';
elsif(sys_clk'event and sys_clk='1') then
:
:
end if;
end if;
a_out <= tmp; -- at falling edge
d_b_out <= NOT tmp; -- at falling edge
b_out <= d_b_out; -- delayed by 10ns - at rising edge
:
:

I am not sure as the Input clock has a frequeny of 50MHz and the outputs 
are at 150KHz.

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Robert wrote:
> Is it ok to add a min delay(is 10ns too much?)
Only you know that...

> just by adding a temp register to delay out_b?
With a 100MHz clock thats the only way to do it...

Author: Wil (Guest)
Posted on:

Rate this post
0 useful
not useful
How do I introduce a 180° phase shift between a_out and b_out. I tried 
using an inverting output. But when dutycycle is 10% for a_out, it is 
90% for b_out. But I want a 10% dutycycle for b_out with 180° phase 
shift.

Any suggestions?

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Wil wrote:
> How do I introduce a 180° phase shift between a_out and b_out.
> I tried using an inverting output.
A phase shift is only defined for sinusoidal signals. And then inverting 
is correct.

> How do I introduce a 180° phase shift between a_out and b_out.
What you want in fact is a delay of half the cycle duration for one of 
the signals.

: Edited by Moderator
Author: Wil (Guest)
Posted on:

Rate this post
0 useful
not useful
Yes. Exactly. But the main clock is 50MHz and the outputs are 150KHz. 
How do I give a synthesizable delay.

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Wil wrote:
> How do I give a synthesizable delay.
Use a second PWM unit that counts half a cycle delayed.
Or simply use a shift register.

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.