Forum Discussion
Altera_Forum
Honored Contributor
11 years agoHi, thanks you two for your replies and your time !!
Hey FvM, the idea was to use natural sampling, how could i loose those pwm edges? i checked my sine vector in modelsim and it really seems that i just have half a sine, buthow does this happen. I thought when the variable x gets calculated its range is from 1 to -1 and this value is casted and stored in the vector? I have the period of 20 ms in which i put 500 sine values. The triangular impulse has a period of 8µs. So after 5 triangle impulses i need a new sine value. So i have the countSine value run to 2000 and update the sinetabe The compare function gets a new sine value every 5 Right now i dont know why i just didnt divide the sine in 5000 intervals seems much more intuitive... I post the complete code with some comments below: Cheers Timlibrary IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--use IEEE.STD_LOGIC_ARITH.ALL; --bad
--use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use IEEE.NUMERIC_STD.all; --good --to_unsigned to_signed <- integer to ..
use ieee.math_real.all;
entity PWM is
Port (
CLOCK : in STD_LOGIC;
RESET : in STD_LOGIC;
PWM_OUTPUT : out STD_LOGIC
);
end PWM;
architecture pwm_process of PWM is
SIGNAL Timer : integer range -2048 to 2047 := 0;
SIGNAL countSine : integer range 0 to 4095 := 4095;
SIGNAL incSineTable : integer range 0 to 500 := 500;
SIGNAL TimerDir : STD_LOGIC :='1';
SIGNAL SinValue : std_logic_vector(8 downto 0) := (others =>'0');
type table is array (0 to 499) of std_logic_vector(8 downto 0);
function init_table return table is
variable x: real;
variable var: table;
begin
for i in 0 to 499 loop
x:= SIN(real(i)*MATH_PI/real(499));
var(i):=std_logic_vector(to_signed(INTEGER(x*real(100)),9));
end loop;
return var;
end;
constant sinTable : table := init_table;
begin
---------------------------------------------------------------------------------
-------------------------Timer Direction Function--------------------------------
---------------------------------------------------------------------------------
--input clokc 50 MHz Timer counts to 200 -> 8µs period time
TimerDirection:process (CLOCK,RESET,TimerDir,Timer)
begin
if RESET = '0' then
TimerDir <= '1';
elsif CLOCK'event and CLOCK ='1' then
if (Timer =99) then
TimerDir <= '0';
end if;
if (Timer =-99) then --1
TimerDir <= '1';
end if;
end if;
--end if;
end process TimerDirection;
----------------------------------------------------------------------------------
--------------------------------Timer counting-----------------------------------
----------------------------------------------------------------------------------
CountingTimer: process (CLOCK,RESET,TimerDir,Timer)
begin
if RESET = '0' then
--Timer<= (others => '0');
Timer <= 0;
elsif CLOCK'event and CLOCK ='1' then
if (TimerDir ='1') then
Timer <=Timer + 1;
end if;
if (TimerDir ='0') then
Timer <=Timer - 1;
end if;
end if;
end process CountingTimer;
---------------------------------------------------------------------------------
-------------------------------Update Sine Value --------------------------------
---------------------------------------------------------------------------------
-- Timer 2500 cycles in 20ms 500 sine values
-- every 5 cycles new sine value -> countSine to 2000
UpdateSineValue : process (CLOCK, RESET)
begin
if RESET = '0' then
incSineTable <= 0;
countSine <= 0;
elsif CLOCK'event and CLOCK ='1' then
SinValue <= sintable(incSineTable);
if incSineTable = 500 then
incSineTable <= 0;
end if;
countSine <= countSine +1;
if (countSine = 2000) then
incSineTable <= incSineTable +1;
end if;
end if;
end process UpdateSineValue;
-------------------------------------------------------------------------------------
---------------------------- TimerCompare Function----------------------------
-------------------------------------------------------------------------------------
TimerCompare: process (CLOCK,RESET,TimerDir,Timer)
begin
if RESET = '0' then
PWM_OUTPUT <= '1';
elsif CLOCK'event and CLOCK ='1' then
--if (SinValue = to_signed(Timer,8)) and (Timerdir<='1')then
if SinValue = std_logic_vector(to_signed(Timer,9)) and (Timerdir<='1')then
PWM_OUTPUT <= '0';
end if;
if SinValue = std_logic_vector(to_signed(Timer,9)) and (Timerdir<='0')then
PWM_OUTPUT <= '1';
end if;
end if;
end process TimerCompare;
end pwm_process;