From df418208aa0570a99f6ab6657d54ee65d6162168 Mon Sep 17 00:00:00 2001 From: Friedrich Beckmann Date: Wed, 15 Mar 2023 22:30:08 +0100 Subject: added de1_sine sinewave generator for ADC/DAC board I added a sinewave generator based on DDS in VHDL to generate a sinewave with the ADC/DAC board. This can be used to demonstrate the Aliasing Lowpass filter. --- src/de1_sine.vhd | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/sine_rtl.vhd | 56 ++++++++++++++++++++++++++++++ src/t_de1_sine.vhd | 80 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 235 insertions(+) create mode 100644 src/de1_sine.vhd create mode 100644 src/sine_rtl.vhd create mode 100644 src/t_de1_sine.vhd (limited to 'src') diff --git a/src/de1_sine.vhd b/src/de1_sine.vhd new file mode 100644 index 0000000..d3073f2 --- /dev/null +++ b/src/de1_sine.vhd @@ -0,0 +1,99 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity de1_sine is + port ( + CLOCK_50 : in std_ulogic; + KEY0 : in std_ulogic; + SW : in std_ulogic_vector(9 downto 0); + DAC_MODE : out std_ulogic; + DAC_WRT_A : out std_ulogic; + DAC_WRT_B : out std_ulogic; + DAC_CLK_A : out std_ulogic; + DAC_CLK_B : out std_ulogic; + DAC_DA : out std_ulogic_vector(13 downto 0); + DAC_DB : out std_ulogic_vector(13 downto 0); + POWER_ON : out std_ulogic; + ADC_CLK_A : out std_ulogic; + ADC_CLK_B : out std_ulogic; + ADC_OEB_A : out std_ulogic; + ADC_OEB_B : out std_ulogic; + LEDR : out std_ulogic_vector(9 downto 0)); +end de1_sine; + +architecture rtl of de1_sine is + + component sine is + port ( + clk : in std_ulogic; + rst_n : in std_ulogic; + phase_inc_i : in std_ulogic_vector(9 downto 0); + phase_o : out std_ulogic_vector(9 downto 0); + sample_o : out std_ulogic_vector(13 downto 0)); + end component sine; + + -- component ports + signal clk : std_ulogic; + signal rst_n : std_ulogic; + signal phase_inc_reg : std_ulogic_vector(9 downto 0); + signal sample : std_ulogic_vector(13 downto 0); + signal daca_reg1, daca_reg2 : std_ulogic_vector(13 downto 0); + signal dacb_reg1, dacb_reg2 : std_ulogic_vector(13 downto 0); + signal phase : std_ulogic_vector(9 downto 0); + +begin + + phase_inc_reg <= "0000000000" when rst_n = '0' else SW when rising_edge(clk); + + sinegen : sine + port map ( + clk => clk, + rst_n => rst_n, + phase_inc_i => phase_inc_reg, + phase_o => phase, + sample_o => sample); + + -- clock and reset signal + clk <= CLOCK_50; + rst_n <= KEY0; + + LEDR <= SW; + + -- DAC in dual-port mode + DAC_MODE <= '1'; + DAC_WRT_A <= clk; + DAC_WRT_B <= clk; + DAC_CLK_A <= clk; + DAC_CLK_B <= clk; + + -- Register to sinegen outputs to relax timing + daca_reg1 <= sample when rising_edge(clk); + daca_reg2 <= daca_reg1 when rising_edge(clk); + dacb_reg1 <= phase & "0000" when rising_edge(clk); + dacb_reg2 <= dacb_reg1 when rising_edge(clk); + + -- DAC on board has 00000000000000 as minimum value + -- and 11111111111111 as maximum value + -- therefore the conversion has to look like this + -- input signed value output DAC value + -- minimum 10000000000000 00000000000000 + -- zero 00000000000000 10000000000000 + -- maximum 01111111111111 11111111111111 + + -- assign to DAC channels + DAC_DA <= "10000000000000" WHEN rst_n = '0' ELSE + (NOT(daca_reg2(13)) & daca_reg2(12 downto 0)) WHEN falling_edge(clk); + DAC_DB <= "10000000000000" when rst_n = '0' else + dacb_reg2 when falling_edge(clk); + + -- ADC section all off! + ADC_CLK_A <= '0'; + ADC_CLK_B <= '0'; + ADC_OEB_A <= '0'; + ADC_OEB_B <= '0'; + + -- switch on DAC/ADC + POWER_ON <= '1'; + +end architecture; diff --git a/src/sine_rtl.vhd b/src/sine_rtl.vhd new file mode 100644 index 0000000..4bc9dd2 --- /dev/null +++ b/src/sine_rtl.vhd @@ -0,0 +1,56 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.all; + +entity sine is + port (clk : in std_ulogic; + rst_n : in std_ulogic; + phase_inc_i : in std_ulogic_vector(9 downto 0); + phase_o : out std_ulogic_vector(9 downto 0); + sample_o : out std_ulogic_vector(13 downto 0)); +end entity; + +architecture rtl of sine is + + signal phase : unsigned(9 downto 0); + + type rom_t is array (0 to 1023) of signed(13 downto 0); + + function sine_rom_init_f return rom_t is + variable phase_real : real := 0.0; + variable sinereal : real; + variable sinequan : signed(13 downto 0); + variable rom_v : rom_t; + begin + for i in 0 to 1023 loop + phase_real := 2.0 * MATH_PI * real(i) / 1024.0; + sinereal := sin(phase_real); + sinequan := to_signed(integer(sinereal * real(2**13-1)), 14); + rom_v (i) := sinequan; + end loop; + return rom_v; + end function; + + constant rom : rom_t := sine_rom_init_f; + + signal rom_out_reg : signed(13 downto 0); + signal rom_index_reg : integer range 0 to 1023; + +begin + + -- phase accumulator + phase <= "0000000000" when rst_n = '0' else + phase + unsigned(phase_inc_i) when rising_edge(clk); + + rom_index_reg <= to_integer(phase) when rising_edge(clk); + + rom_out_reg <= rom(rom_index_reg) when rising_edge(clk); + + sample_o <= "00000000000000" when rst_n = '0' else + std_ulogic_vector(rom_out_reg) when rising_edge(clk); + + phase_o <= "0000000000" when rst_n = '0' else + std_ulogic_vector(phase) when rising_edge(clk); + +end architecture rtl; diff --git a/src/t_de1_sine.vhd b/src/t_de1_sine.vhd new file mode 100644 index 0000000..67b81ae --- /dev/null +++ b/src/t_de1_sine.vhd @@ -0,0 +1,80 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity t_de1_sine is +end entity; + +architecture beh of t_de1_sine is + +component de1_sine is + port ( + CLOCK_50 : in std_ulogic; + KEY0 : in std_ulogic; + SW : in std_ulogic_vector(9 downto 0); + DAC_MODE : out std_ulogic; + DAC_WRT_A : out std_ulogic; + DAC_WRT_B : out std_ulogic; + DAC_CLK_A : out std_ulogic; + DAC_CLK_B : out std_ulogic; + DAC_DA : out std_ulogic_vector(13 downto 0); + DAC_DB : out std_ulogic_vector(13 downto 0); + POWER_ON : out std_ulogic; + ADC_CLK_A : out std_ulogic; + ADC_CLK_B : out std_ulogic; + ADC_OEB_A : out std_ulogic; + ADC_OEB_B : out std_ulogic; + LEDR : out std_ulogic_vector(9 downto 0)); +end component; + + signal clk : std_ulogic; + signal rst_n : std_ulogic; + + signal dac_mode, dac_wrt_a, dac_wrt_b, dac_clk_a, + dac_clk_b, power_on, adc_clk_a, adc_clk_b, + adc_oeb_a, adc_oeb_b : std_ulogic; + signal dac_da, dac_db : std_ulogic_vector(13 downto 0); + signal ledr, sw : std_ulogic_vector(9 downto 0); + + signal simstop : boolean; + +begin + + dut : de1_sine + port map( + CLOCK_50 => clk, + KEY0 => rst_n, + SW => sw, + DAC_MODE => dac_mode, + DAC_WRT_A => dac_wrt_a, + DAC_WRT_B => dac_wrt_b, + DAC_CLK_A => dac_clk_a, + DAC_CLK_B => dac_clk_b, + DAC_DA => dac_da, + DAC_DB => dac_db, + POWER_ON => power_on, + ADC_CLK_A => adc_clk_a, + ADC_CLK_B => adc_clk_b, + ADC_OEB_A => adc_oeb_a, + ADC_OEB_B => adc_oeb_b, + LEDR => ledr + ); + + clk_p : process + begin + clk <= '0'; + wait for 10 ns; + clk <= '1'; + wait for 10 ns; + if simstop then + wait; + end if; + end process; + + rst_n <= '0', '1' after 50 ns; + + simstop <= false, true after 30 us; + + sw <= "0000000001"; + +end architecture; \ No newline at end of file -- cgit v1.2.3