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:
Código:
-- 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
Código:
-- 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?