EmbDev.net

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


von Robert (Guest)


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:
1
entity Gen_150 is
2
port ( sys_clk,reset: in std_logic; --sys_clk:50MHz
3
a_out, b_out: out std_logic);       --a_out,b_out:150KHz
4
end Gen_150 ;
5
 
6
architecture bhv of Gen_150 is
7
 
8
signal count: integer:=0;
9
signal tmp : std_logic := '1';
10
11
begin
12
 
13
process(sys_clk,reset)
14
begin
15
if(reset='0') then
16
count<=0;
17
tmp<='1';
18
elsif(sys_clk'event and sys_clk='1') then
19
  count <=count+1;
20
21
  if (count = 166) then   -- dutycycle=50% ((50000000/150000)/2)
22
     tmp <= NOT tmp;
23
     count<= 0;  
24
  end if;
25
end if;
26
a_out <= tmp;
27
b_out <= NOT tmp after 10ns; -- output delayed by 10ns
28
end process;
29
 
30
end bhv;

Thank you!

von Duke Scarring (Guest)


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

von Okay (Guest)


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?

von Lothar M. (lkmiller) (Moderator)


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:
1
signal count: integer:=0;
2
signal pwm: integer:=100;
3
:
4
:
5
elsif(sys_clk'event and sys_clk='1') then
6
  count <=count+1;
7
8
  if (count = 332) then
9
     count <= 0;  
10
  end if;
11
   
12
end if;
13
14
tmp <= '1' when (count < pwm) else '0';
15
:
16
:
17
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...

von Robert (Guest)


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';
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.numeric_std.ALL;
4
 
5
entity Gen_150 is
6
port ( sys_clk,reset: in std_logic;
7
a_out, b_out: out std_logic);
8
end Gen_150 ;
9
 
10
architecture bhv of Gen_150 is
11
 
12
signal count: integer:=0;
13
signal tmp : std_logic := '1';
14
signal counter: integer := 0;
15
signal pwm: integer := 0;
16
17
begin
18
 
19
process(sys_clk,reset)
20
begin
21
if(reset='0') then
22
count<=0;
23
tmp<='1';
24
elsif(sys_clk'event and sys_clk='1') then
25
  count <=count+1;
26
  --counter <= counter +1;
27
  if (count = 332) then
28
    -- tmp <= NOT tmp;
29
     count<= 0;  
30
  end if;
31
end if;
32
tmp <= '1' when(count < pwm) else tmp <= '0'; 
33
34
a_out <= tmp;
35
b_out <= NOT tmp;
36
37
end process;
38
39
Ramp : process (reset, sys_clk)
40
begin
41
  if reset = '0' then
42
    pwm      <= 0;
43
  elsif rising_edge(sys_clk)  then
44
    counter <= counter +1;
45
    if counter<=500000 then -- 500000 cycles =10ms
46
      
47
        case  counter  is
48
          when  50000     =>  pwm  <= 25;    
49
          when  100000  =>  pwm  <= 33;  
50
          when  150000  =>  pwm  <= 44;  
51
          when  200000  =>  pwm  <= 66;  
52
          when  250000  =>  pwm  <= 77;  
53
          when  300000  =>  pwm  <= 99;            
54
          when  350000  =>  pwm  <= 120;  
55
          when  400000  =>  pwm  <= 132;  
56
          when  450000  =>  pwm  <= 145;  
57
          when  500000  =>  pwm  <= 166;  
58
          
59
          when  others  =>  pwm  <= 0;    
60
        end case;
61
      
62
    else
63
      pwm      <= 0;
64
    end if;
65
  end if;
66
67
end process Ramp;
68
 
69
end bhv;

von Lothar M. (lkmiller) (Moderator)


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
von Robert (Guest)


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?

von Robert (Guest)


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

von Duke Scarring (Guest)


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

von Robert (Guest)


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?
1
if(reset='0') then
2
count<=0;
3
tmp<='1';
4
elsif(sys_clk'event and sys_clk='1') then
5
:
6
:
7
end if;
8
end if;
9
a_out <= tmp; -- at falling edge
10
d_b_out <= NOT tmp; -- at falling edge
11
b_out <= d_b_out; -- delayed by 10ns - at rising edge
12
:
13
:

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

von Lothar M. (lkmiller) (Moderator)


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...

von Wil (Guest)


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?

von Lothar M. (lkmiller) (Moderator)


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
von Wil (Guest)


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.

von Lothar M. (lkmiller) (Moderator)


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]
  • [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.