- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I would like to know is there any possibility to use always inside for loop?? please anybody explain the errors associated with my code both logical and coding syntax issues ThankYOU
freqs.v
(Virus scan in progress ...)
Link Copied
5 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Hi, I would like to know is there any possibility to use always inside for loop?? please anybody explain the errors associated with my code both logical and coding syntax issues ThankYOU --- Quote End --- I think you have been struggling for some time with your pwm work. I am afraid Your current coding is just wrong all over. Moreover your algorithm plan is not clear. I am here volunteering the below piece of code which is almost a precision pwm generator. and it can't be simpler(well it depends). The only drawback is that I have done it in matlab code and leave it to you to translate to hdl. it is just an accumultor and comparator. Don't worry at this stage about how it works. you can also avoid division /100 on the duty cycle by some simple bit shift trick (rescale duty cycle to divide by 128)
clear all;
n = 1000; %this test length
clk = 100; %MHz system clock
f1 = 1; %MHz required output frequency
%%%%%%%%%%%% accumulator %%%%%%%%%%%%%%%
m = 1024; %(assumed) lut size
tw = floor(m*f1/clk); %tuning word for half cycle
ptr = 0; %pointer to lut
for i = 1:n
ptr = round(mod(ptr + tw, m));
lut_data(i) = (ptr-1)*64; %lut computed per pointer
end
%%%%%%%%%%%%% comparator %%%%%%%%%%%%%
clkout = zeros(1,n);
duty = 1; %1 ~ 100 percent
threshold = 32768*duty*2/100;
for i = 1:n
if lut_data(i) <= threshold, clkout(i) = 32767; end;
end
%%%%%%%%%%%% check results %%%%%%%%%%%
figure;plot(lut_data,'g-'); hold
plot(clkout,'r.-');
grid;
d = diff(clkout);
b = find(d);
c = diff(b);
duty_out = round(100*c(2)/(c(1)+c(2)))
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
here's a working PWM module
--Author: some guy at digikey
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY pwm IS
GENERIC(
sys_clk : INTEGER := 50_000_000; --system clock frequency in Hz
pwm_freq : INTEGER := 100_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 : INTEGER RANGE 0 TO period/2 := 0; --number of clocks in 1/2 duty cycle
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 <= 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
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) 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) 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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- here's a working PWM module --- Quote End --- yes you can use a basic counter as such. Your design however expects a fixed freq generic but if freq is meant to be an input then you need to divide to get period cycles which can be avoided using accumulator. accumulator approach additionally supports fractional clk/freq and not just integer result. for a precision pwm (really precise) avoiding division is to use sine LUT + accumulator + comparator.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Thankyou inputting a frequency and duty cycle value , using counters concepts pwm generation is successful . as u said, to overcome the limitations of counters I am trying to learn accumulator techniques. But target or problem in my code is that... I need to generate a set of frequencies and their pwm from system clock . Like eg... 50mhz my system clock range of frequency 5mhz-30mhz with stepsize 5mhz.... ie, 5,10,15,20,25,30 like that. so I would like to add a loop to select the current frequency and then rest of program will be same. Thankyou- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Hi, Thankyou inputting a frequency and duty cycle value , using counters concepts pwm generation is successful . as u said, to overcome the limitations of counters I am trying to learn accumulator techniques. But target or problem in my code is that... I need to generate a set of frequencies and their pwm from system clock . Like eg... 50mhz my system clock range of frequency 5mhz-30mhz with stepsize 5mhz.... ie, 5,10,15,20,25,30 like that. so I would like to add a loop to select the current frequency and then rest of program will be same. Thankyou --- Quote End --- with the simple counter technique you can only generate frequencies that differ in the ratio result of clk/freq and your resolution step is inherently limited to that. In the accumulator approach you can get much finer resolution (on average) since it is based on phase accumulation. In fact you don't need frequency step as input in any case. also I notice that the duty cycle ratio approach posted by mhouse1 doesn't make sense to me for example if duty cycle is 50% then he multiplies that by period say 50*10 then divides it by 2^8/2 ? where is the 100 then as 50 is ratio to 100. May be he assumes some rescaling at the 8 bit input (duty). Thus in both cases(counter or accum) you have two divisions to be dealt with(clk/freq and conversion of duty ratio). The accumulator bypasses the first division i.e. it implements it inherently but you need to precompute tuning word in both cases, the duty ratio is better converted from /100 ratio to /128 ratio

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page