# Generar Onda Senoidal en FPGA



## eddyp82 (Dic 28, 2008)

Hola a todos!

Estoy trabajando en un proyecto con FPGA, necesito basicamente saber como puedo generar una señal senoidal de 50 Hz y tambien señales triangulares, esto es para hacer modulacion PWM. He visto que se puede hacer mediante look up table o mediante programacion de un algoritmo CORDIC, pero no me queda claro como implementarlo en la FPGA.

Ojala me puedan ayudar

Saludos

Edgardo


----------



## Elvic (Ene 2, 2009)

saludos

puedes checar esta pagina.

tiene  el codigo completa para realizar una onda sinusoidal 

http://www.doulos.com/knowhow/vhdl_designers_guide/models/sine_wave_generator/


y esta es una captura de pantalla de la simulacion en active-HDL..


----------



## eddyp82 (Ene 2, 2009)

Muchas Gracias Elvic

La pagina es muy buena, ahora mismo la estoy viendo,  en caso de resultarme mis simulaciones, lo posteo acá...

Saludos


----------



## jaeg (Feb 17, 2009)

Que tal he estado probando el codigo que aparece en el link 
http://www.doulos.com/knowhow/vhdl_designers_guide/models/sine_wave_generator/ 
No he logrado obtener la forma sinusoidal que se presenta en la los archivos adjustos de Elvic. Por otro lado observo que existen otros dos pines que no aparecen en el codigo VHDL "SEL y WAVE OUT".

Estoy empleando el Started Spartan 3E Kit. 

Podrian ayudarme con un poco mas de información.

saludos


----------



## Elvic (Feb 17, 2009)

saludos jaeq

Originalmente el código que aparece en el link es solamente para generar la onda sinusoidal.
EL pin  "SEL"( de seleccionar), se agrego, puesto el código debería también generar  la onda triangular, por esa razón fue ese pin

sin embargo la salida "wave_out"  debe aparecer pues es de hay donde se toman los datos.


suerte


----------



## jaeg (Feb 18, 2009)

Que tal Elvic.

Oye y como lograste la triangular?

saludos


----------



## Elvic (Feb 18, 2009)

saludos 

en el archivo *(sine_package)* que se debe adjuntar a la compilación,  hay una lista de valores *(table_value*) que formara la onda sinusoidal; esa misma tabla se modifica y se ponen los números correspondiente para generar la onda triangular.

 por ejemplo este es parte de la tabla de datos paar generar la onda sinusoidal 


```
case table_index is
      when 0 =>
        table_value := 1;
      when 1 =>
        table_value := 2;
      when 2 =>
        table_value := 4;
      when 3 =>
        table_value := 5;
      when 4 =>
        table_value := 7;
      when 5 =>
        table_value := 9;
      when 6 =>
        table_value := 10;
      when 7 =>
        table_value := 12;
```
la siguiente seria la tabla modificada para generar la triangular

```
case table_index is
      when 0 =>
        table_value := 1;
      when 1 =>
        table_value := 1;
      when 2 =>
        table_value := 2;
      when 3 =>
        table_value := 3;
      when 4 =>
        table_value := 4;
      when 5 =>
        table_value := 5;
      when 6 =>
        table_value := 6;
      when 7 =>
        table_value := 7;
```

o podrias usar la misma variable "table_index" para de hay tomar los valores para la onda triangular

suerT


----------



## jaeg (Feb 20, 2009)

Gracias me encuentro trabajando en ello.

saludos


----------



## kristoft (May 31, 2011)

Hola, saludos a todos.. yo soy nuevo en el lenguaje VHDL y tambien en la programacion de FPGA's, aun no puedo obtener la forma de onda que aparece en la imagen de ELVIC, estoy simulando con ModelSim SE PLUS 6.5 .. espero me puedan ayudar..



			
				kristoft dijo:
			
		

> Hola, saludos a todos.. yo soy nuevo en el lenguaje VHDL y tambien en la programacion de FPGA's, aun no puedo obtener la forma de onda que aparece en la imagen de ELVIC, estoy simulando con ModelSim SE PLUS 6.5 .. espero me puedan ayudar..



Hola Elvic, intente una vez mas con el programa model sim y pude obtener la onda senoidal. Ahora tengo otra pregunta, ¿Como puedo modificar la frecuencia de esa señal?. 

Espero me puedan ayudar. 

Saludos y buen dia


----------



## metalpatriot (Ago 18, 2015)

saludos amigos espero no haber llegado demasiado tarde a este tema, soy novato en esto de VHDL y pues he utilizado este codigo para simular la onda senoidal con el modelsim pero el problema es que en la onda de salida solo veo valores numericos, como un vector. Que debo configurar para lograr ver la forma de onda?


----------



## Scooter (Ago 18, 2015)

Pues tendrás que hacer un conversor D-A. Supongo que vale con uno resistivo.


----------



## metalpatriot (Ago 18, 2015)

Gracias Scooter, ya supe luego de mucho buscar jeje, resulta que se debe cambiar el formato de la señal a analogica y listo.

Ya he logrado simular tanto la sinuidal como la señal triangular, ahora me pregunto como cambiar la frecuencia de dicha señal


----------



## henryjdr92 (Ago 26, 2015)

metalpatriot dijo:


> Gracias Scooter, ya supe luego de mucho buscar jeje, resulta que se debe cambiar el formato de la señal a analogica y listo.
> 
> Ya he logrado simular tanto la sinuidal como la señal triangular, ahora me pregunto como cambiar la frecuencia de dicha señal




Y si quisiera modificar la amplitud también, qué sugieren?


----------



## chclau (Ago 26, 2015)

La frecuencia de la señal depende de la velocidad a la que se generan las muestras. Si se genera una señal que funcione, por ejemplo, a la mitad de la frecuencia del reloj principal y con ella se habilita la generacion de nuevos valores, la frecuencia de salida sera la mitad.

Para cambiar la amplitud, hay que multiplicar los valores de salida por un valor de "amplificacion".


----------



## henryjdr92 (Ago 27, 2015)

chclau dijo:


> La frecuencia de la señal depende de la velocidad a la que se generan las muestras. Si se genera una señal que funcione, por ejemplo, a la mitad de la frecuencia del reloj principal y con ella se habilita la generacion de nuevos valores, la frecuencia de salida sera la mitad.
> 
> Para cambiar la amplitud, hay que multiplicar los valores de salida por un valor de "amplificacion".



Gracias chclau, ya pude variar la frecuencia a discreción; pero sin embargo, con respecto a la amplitud, aún no me queda del todo claro esa ganancia o valor de "amplificación"


----------



## chclau (Ago 28, 2015)

henryjdr92 dijo:


> Gracias chclau, ya pude variar la frecuencia a discreción; pero sin embargo, con respecto a la amplitud, aún no me queda del todo claro esa ganancia o valor de "amplificación"




Bueno, aqui adjunto un ejemplo. El archivo "saw" genera una onda triangular simetrica, pero acepta tambien un parametro de ganancia.

El archivo genera la "ROM" con los datos de la funcion en forma automatica en la primera seccion (Generate)

El primer proceso actualiza el acumulador de fase.
El segundo proceso calcula los valores de salida segun los valores de tabla y los afecta con la ganancia.

A continuacion la fuente:


```
-- File Name   : saw.vhd
--  Comments   : Generate sawtooth wave
------------------------------------------------------------------
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;
use ieee.numeric_std.ALL;

ENTITY saw IS

PORT (	
	clk 		: in std_logic;
	reset 		: in std_logic;
	
	gain		: in std_logic_vector(3 downto 0);
	dout 		: out std_logic_vector(7 downto 0)
);
END saw ;--
--
ARCHITECTURE rtl OF saw IS

	CONSTANT ROMSIZE : INTEGER  := 16;
	CONSTANT ROM_W   : INTEGER  := 7;
	TYPE VALTAB IS ARRAY(0 TO ROMSIZE-1) OF signed (7 DOWNTO 0);
	
	signal VALROM: VALTAB;
	signal phase_accum : unsigned(3 downto 0); 
	signal dout_gain   : signed(11 downto 0); 
	
BEGIN

	-- Create saw values table,
	GENROM:
	FOR idx in 0 TO ROMSIZE-1 GENERATE
		CONSTANT offset: 	INTEGER := -8;
		CONSTANT ysc:   	INTEGER := idx+offset;
		CONSTANT yn: 	    SIGNED (7 DOWNTO 0) := TO_SIGNED(ysc, 8);
	BEGIN
		VALROM(idx) <= yn; 
	END GENERATE; 
	
	-- phase accumulator
        process (clk, reset) begin
        if (reset = '1') then
            phase_accum <= (others => '0');
        elsif (rising_edge(clk)) then
	    phase_accum <= phase_accum + 1;
	end if;	
	end process;

	-- phase lookup + gain
        process (clk, reset) begin
        if (reset = '1') then
            dout_gain	<= (others => '0');
        elsif (rising_edge(clk)) then
	    dout_gain	<= signed(gain) * VALROM(to_integer(phase_accum));
	end if;
	end process;
	
	dout <=	std_logic_vector(dout_gain(7 downto 0));
	
END;
```

Aqui tienes un test bench que verifica la funcion del archivo



```
-- File Name   : tb_saw.vhd
--  Comments   : Test bench for the saw waveform generator
------------------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_textio.all;
    use ieee.numeric_std.ALL;
    
entity tb_saw is
end entity;

architecture test of tb_saw is

    constant PERIOD  : time    := 20 ns;		-- clk = 50MHz
    signal clk       : std_logic := '0';
    signal reset     : std_logic := '1';
    signal gain      : std_logic_vector (3 downto 0);
    signal saw_out   : std_logic_vector (7 downto 0);
    signal endSim	 : boolean   := false;

    component saw is

	PORT (	
		clk 		: in std_logic;
		reset 		: in std_logic;
		gain		: in std_logic_vector(3 downto 0);
		dout 		: out std_logic_vector(7 downto 0)
	);
	END component;
    

begin
        clk    	<= not clk after PERIOD/2;
	
	stim_proc: process
	begin
		wait for PERIOD*5;
		reset   <= '0';
		gain   <= std_logic_vector(to_signed(1, 4));
		wait for PERIOD*80;
		gain   <= std_logic_vector(to_signed(3, 4));
		wait for PERIOD*80;
		gain   <= std_logic_vector(to_signed(-1, 4));
		wait for PERIOD*80;
		wait until (clk = '1');
		
		endSim  <= true;
	end process;
		
	-- End the simulation
	process 
	begin
		if (endSim) then
			assert false 
				report "End of simulation." 
				severity failure; 
		end if;
		wait until (clk = '1');
	end process;	

    saw_inst : saw
    port map (
        clk      => clk,
        reset    => reset,
        gain     => gain,
	dout	 => saw_out
    );

end architecture;
```

El banco de pruebas usa tres ganancias, uno, tres y menos uno, y se puede ver el resultado del mismo en la forma de onda:



Te dejo una pregunta para ti, para que la pienses y practiques. Que sucede si usas distintos valores de la triangular, o de ganancia, tales que el resultado se escapa de la precision que tiene esta solucion?

Ejemplo, los valores de la tabla asi como esta van de -8 a 7 con ganancia unitaria. Que pasaria si permites que la ganancia sea mas grande, por ejemplo de 8 bits, y al multiplicar 7 por la maxima ganancia en este caso que es 127, el resultado desborda ya que obviamente no puede ser representado con ocho bits.

Como se ve la falla que ocurre y como lo resolverias?


----------

