http://www.ciudadoscura.com/electronica/1/gener ador-de-senal-sinusoidal-en-vhdl.html Generador de señal sinusoidal en VHDL Es posible que se necesite generar algún tipo de señal mediante VHDL y una FPGA. Sabemos que comúnmente, una FPGA solo genera señales de tipo lógico, es decir, estado alto y bajo. Es posible obtener una señal más allá de esos dos estados usando un convertidor digital-análogo R-2R cuyo funcionamiento se describe en el siguiente video.
En éste caso tendremos un número de 8 bits (1 byte). Utilizando un pequeño programa en Matlab nos es posible obtener valores dividiendo 1 periodo de la función seno entre el número de muestras que deseemos. A razón de que tenemos 8 bits, nuestro máximo valor en decimal es 255 y el mínimo 0. 11111111(2) 00000000(2)
= =
255(10) 0(10)
A continuación, sabiendo todo lo anterior, pasamos a calcular los valores decimales para 25 muestras en este caso.
clc clear frec = 10^6; t = 0:(1/frec)/25:(1/frec); y = (255/2)*(sin(2*pi*frec*t)+1); plot(t,y,'-k*','LineWidth',1,'MarkerEdgeColor','b') hold on axis([0 (1/frec) 0 255]) for n = 0:24 xl = [(n*((1/frec)/25)) (n*((1/frec)/25))]; yl = [0 255]; line(xl,yl); (255/2)*(sin(2*pi*frec*(n*((1/frec)/25)))+1) end
Ahora, en la consola de Matlab tendremos 25 valores decimales pero necesitamos que sean enteros para poder usar los 8 bits, entonces aproximamos los valores a su número entero más cercano. Luego de esto, pasamos a convertir cada número de decimal a binario y ya tendremos nuestra tabla de 25 valores. Teniendo la tabla solo nos queda describir el funcionamiento del generador con VHDL. A continuación un ejemplo.
--------------------------------------The Dark City --www.ciudadoscura.com --Camilo Rojas G. ------------------------------------library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity gen is port ( clk : in STD_LOGIC; reset : in STD_LOGIC; seno : out STD_LOGIC_VECTOR(7 downto 0));
end gen; architecture Behavioral of gen is signal contador: natural; begin --Tabla de la señal sinusoidal con 25 muestras. process(contador) begin case(contador) is when 0 => seno <= "01111111"; when 1 => seno <= "10011111"; when 2 => seno <= "10111101"; when 3 => seno <= "11010111"; when 4 => seno <= "11101011"; when 5 => seno <= "11111001"; when 6 => seno <= "11111111"; when 7 => seno <= "11111101"; when 8 => seno <= "11110011"; when 9 => seno <= "11100010"; when 10 => seno <= "11001010"; when 11 => seno <= "10101110"; when 12 => seno <= "10001111"; when 13 => seno <= "01110000"; when 14 => seno <= "01010001"; when 15 => seno <= "00110101"; when 16 => seno <= "00011101"; when 17 => seno <= "00001100"; when 18 => seno <= "00000010"; when 19 => seno <= "00000000"; when 20 => seno <= "00000110"; when 21 => seno <= "00010100"; when 22 => seno <= "00101000"; when 23 => seno <= "01000010"; when 24 => seno <= "01100000"; when others => seno<="00000000"; end case; end process; process(clk, reset) begin if(reset = '1') then contador <= 0; elsif(clk'event and clk='1') then if(contador = 24) then contador <= 0; else contador <= contador + 1; end if; end if; end process; end Behavioral;
Ahora solo queda definir nuestros pines de salida de
seno (de 8 bits) y nuestro reloj clk.
Recuerda que la frecuencia de la señal será dada por la frecuencia del reloj dividida por el número de muestras que tomamos (25). Fuentes: Stephen Brown, Zvonko Vranesic. Fundamentos de lógica digital con diseño VHDL. Segunda edición.
McGraw-Hill.
2006.
Autor: Camilo R. Rojas G.
OTRA FORMA http://www.doulos.com/knowhow/vhdl_designers_guide/models/sine_wave_generator/ Synthesisable generador de onda sinusoidal Esta página le ofrece un generador de onda sinusoidal personalizable. A continuación se muestra una descripción genérica VHDL de un generador de onda sinusoidal. Se parametriza mediante constantes y subtipos declarados en sine_package. Más abajo es un formulario HTML para que especifique la palabra y tamaños de direcciones para una tabla para almacenar los valores de una onda sinusoidal. Envíe el formulario y un script cortos en Perl se ejecuta en el servidor para generar un personalizado sine_package completa con tabla de búsqueda para usted. Esta aplicación es moderadamente eficiente de la memoria, ya que almacena sólo el primer pi / 2 radianes de valores de seno. El segundo pi / 2 radianes es una imagen especular de la primera en el tiempo y el segundo pi radianes es una imagen de espejo en la amplitud de las primera Pi radianes. Memoria podría ser salvado si los incrementos se registraron en lugar de cada valor absoluto. Se necesitan menos bits por valor, sin embargo, sería necesario hardware adicional para una víbora.
CODIGO: -- Synthesisable design for a sine wave generator -- Copyright Doulos Ltd -- SD, 07 Aug 2003
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.sine_package.all;
entity sine_wave is port( clock, reset, enable: in std_logic; wave_out: out sine_vector_type); end;
architecture arch1 of sine_wave is type state_type is ( counting_up, change_down, counting_down, change_up ); signal state, next_state: state_type; signal table_index: table_index_type; signal positive_cycle: boolean; begin
process( clock, reset ) begin if reset = '1' then state <= counting_up; elsif rising_edge( clock ) then if enable = '1' then state <= next_state; end if; end if; end process;
process( state, table_index ) begin next_state <= state; case state is when counting_up => if table_index = max_table_index then next_state <= change_down; end if; when change_down => next_state <= counting_down; when counting_down => if table_index = 0 then next_state <= change_up; end if; when others => -- change_up
next_state <= counting_up; end case; end process;
process( clock, reset ) begin if reset = '1' then table_index <= 0; positive_cycle <= true; elsif rising_edge( clock ) then if enable = '1' then case next_state is when counting_up => table_index <= table_index + 1; when counting_down => table_index <= table_index - 1; when change_up => positive_cycle <= not positive_cycle; when others => -- nothing to do end case; end if; end if; end process;
process( table_index, positive_cycle ) variable table_value: table_value_type; begin table_value := get_table_value( table_index ); if positive_cycle then wave_out <= std_logic_vector(to_signed(table_value,sine_vector_type'length)); else
wave_out <= std_logic_vector(to_signed(table_value,sine_vector_type'length)); end if; end process;
end;
Lookup Table We will use a short Perl script to generate a lookup table in a package, sine_package. Specify a word size and address size suitable for your application. Values of 8 and 7 will generate a ROM of size 256 bytes.
Tabla de búsqueda Vamos a utilizar un script cortos en Perl para generar una tabla de búsqueda en un paquete, sine_package. Especifique un tamaño de palabra y tamaño de la dirección adecuada para su aplicación. Los valores de 8 y 7 generarán una ROM de tamaño de 256 bytes. 7 Lookup table word size
7 Lookup table address size
Generate sine_package Code
Test Bench Download an example sine wave generator with a test bench: sine_testbench.zip
We have bundled a simple testbench to show how this code works. There's also a Tcl script called go.tcl to drive ModelSim for you. Here's what the output looks like in ModelSim.
Descargue un ejemplo del generador de onda sinusoidal con un banco de pruebas: sine_testbench.zip Hemos incluido un sencillo banco de pruebas para mostrar cómo funciona este código. También hay un script Tcl llamada go.tcl conducir ModelSim para usted. Esto es lo que la salida se ve como en ModelSim.
Synthesis Both Synplicity's Synplify® and Mentor's Leonardo Spectrum® recognised the case statement in function get_table_value as a ROM.
Tanto de Synplicity Synplify ® y de Mentor Leonardo Spectrum ® reconocieron la declaración de caso en función get_table_value como una ROM.