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. --- pnr/de1_sine/de1_sine_pins.tcl | 62 ++++++++++++++++++++++++++ pnr/de1_sine/makefile | 12 +++++ sim/de1_sine/makefile | 8 ++++ sim/de1_sine/makefile.sources | 4 ++ src/de1_sine.vhd | 99 ++++++++++++++++++++++++++++++++++++++++++ src/sine_rtl.vhd | 56 ++++++++++++++++++++++++ src/t_de1_sine.vhd | 80 ++++++++++++++++++++++++++++++++++ 7 files changed, 321 insertions(+) create mode 100644 pnr/de1_sine/de1_sine_pins.tcl create mode 100644 pnr/de1_sine/makefile create mode 100644 sim/de1_sine/makefile create mode 100644 sim/de1_sine/makefile.sources create mode 100644 src/de1_sine.vhd create mode 100644 src/sine_rtl.vhd create mode 100644 src/t_de1_sine.vhd diff --git a/pnr/de1_sine/de1_sine_pins.tcl b/pnr/de1_sine/de1_sine_pins.tcl new file mode 100644 index 0000000..def031e --- /dev/null +++ b/pnr/de1_sine/de1_sine_pins.tcl @@ -0,0 +1,62 @@ +# Pin Configuration +set_location_assignment PIN_L1 -to CLOCK_50 +set_location_assignment PIN_R22 -to KEY0 +set_location_assignment PIN_L22 -to SW[0] +set_location_assignment PIN_L21 -to SW[1] +set_location_assignment PIN_M22 -to SW[2] +set_location_assignment PIN_V12 -to SW[3] +set_location_assignment PIN_W12 -to SW[4] +set_location_assignment PIN_U12 -to SW[5] +set_location_assignment PIN_U11 -to SW[6] +set_location_assignment PIN_M2 -to SW[7] +set_location_assignment PIN_M1 -to SW[8] +set_location_assignment PIN_L2 -to SW[9] +set_location_assignment PIN_R20 -to LEDR[0] +set_location_assignment PIN_R19 -to LEDR[1] +set_location_assignment PIN_U19 -to LEDR[2] +set_location_assignment PIN_Y19 -to LEDR[3] +set_location_assignment PIN_T18 -to LEDR[4] +set_location_assignment PIN_V19 -to LEDR[5] +set_location_assignment PIN_Y18 -to LEDR[6] +set_location_assignment PIN_U18 -to LEDR[7] +set_location_assignment PIN_R18 -to LEDR[8] +set_location_assignment PIN_R17 -to LEDR[9] +# DAC Pins on GPIO Header +set_location_assignment PIN_C19 -to DAC_CLK_A +set_location_assignment PIN_D19 -to DAC_CLK_B +set_location_assignment PIN_C18 -to DAC_DA[0] +set_location_assignment PIN_F15 -to DAC_DA[10] +set_location_assignment PIN_E14 -to DAC_DA[11] +set_location_assignment PIN_G15 -to DAC_DA[12] +set_location_assignment PIN_H13 -to DAC_DA[13] +set_location_assignment PIN_D16 -to DAC_DA[1] +set_location_assignment PIN_C17 -to DAC_DA[2] +set_location_assignment PIN_D15 -to DAC_DA[3] +set_location_assignment PIN_D14 -to DAC_DA[4] +set_location_assignment PIN_F13 -to DAC_DA[5] +set_location_assignment PIN_C14 -to DAC_DA[6] +set_location_assignment PIN_F12 -to DAC_DA[7] +set_location_assignment PIN_G16 -to DAC_DA[8] +set_location_assignment PIN_E15 -to DAC_DA[9] +set_location_assignment PIN_P15 -to DAC_DB[0] +set_location_assignment PIN_G20 -to DAC_DB[10] +set_location_assignment PIN_E19 -to DAC_DB[11] +set_location_assignment PIN_F20 -to DAC_DB[12] +set_location_assignment PIN_D20 -to DAC_DB[13] +set_location_assignment PIN_N22 -to DAC_DB[1] +set_location_assignment PIN_N15 -to DAC_DB[2] +set_location_assignment PIN_N21 -to DAC_DB[3] +set_location_assignment PIN_J15 -to DAC_DB[4] +set_location_assignment PIN_G17 -to DAC_DB[5] +set_location_assignment PIN_H18 -to DAC_DB[6] +set_location_assignment PIN_H17 -to DAC_DB[7] +set_location_assignment PIN_G18 -to DAC_DB[8] +set_location_assignment PIN_E18 -to DAC_DB[9] +set_location_assignment PIN_P18 -to DAC_MODE +set_location_assignment PIN_C20 -to DAC_WRT_A +set_location_assignment PIN_P17 -to DAC_WRT_B +set_location_assignment PIN_C21 -to ADC_CLK_A +set_location_assignment PIN_D21 -to ADC_CLK_B +set_location_assignment PIN_L18 -to ADC_OEB_A +set_location_assignment PIN_K20 -to ADC_OEB_B +set_location_assignment PIN_J18 -to POWER_ON diff --git a/pnr/de1_sine/makefile b/pnr/de1_sine/makefile new file mode 100644 index 0000000..404bf3d --- /dev/null +++ b/pnr/de1_sine/makefile @@ -0,0 +1,12 @@ +PROJECT = de1_sine + + +SOURCE_FILES = \ +../../src/de1_sine.vhd \ +../../src/sine_rtl.vhd + +FAMILY = "Cyclone II" +DEVICE = EP2C20F484C7 +PROGFILEEXT = sof + +include ../makefile diff --git a/sim/de1_sine/makefile b/sim/de1_sine/makefile new file mode 100644 index 0000000..e662da8 --- /dev/null +++ b/sim/de1_sine/makefile @@ -0,0 +1,8 @@ +PROJECT = de1_sine + +include ./makefile.sources + +SOURCE_FILES = $(SYN_SOURCE_FILES) \ +../../src/t_$(PROJECT).vhd + +include ../makefile diff --git a/sim/de1_sine/makefile.sources b/sim/de1_sine/makefile.sources new file mode 100644 index 0000000..5117d72 --- /dev/null +++ b/sim/de1_sine/makefile.sources @@ -0,0 +1,4 @@ +SYN_SOURCE_FILES = \ +../../src/de1_sine.vhd \ +../../src/sine_rtl.vhd + 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