diff --git a/wave_generator.vhd b/wave_generator.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..b6d2b2b8c84f1143bacd0c0e1ec93e23ba0c4b04
--- /dev/null
+++ b/wave_generator.vhd
@@ -0,0 +1,161 @@
+-- TOP module of a wave generator
+-- generic parameters:
+-- N: number of bits of the sine value
+-- f0: fundamental frequency
+-- fs: sampling frequency
+-- Inputs:
+-- CLK, RST
+-- WAVE_SEL : selects the type of waveform (sine, square, triangle, saw-tooth)
+-- Outputs:
+-- WAV: the wave output
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use ieee.math_real.all;
+
+entity wave_generator is
+    generic (
+        G_N  : integer := 8;
+        G_f0 : real    := 1.0;
+        G_fs : real    := 100.0
+        );
+    port (
+        I_clk      : in  std_logic;
+        I_rst      : in  std_logic;
+        I_wave_sel : in  std_logic_vector(1 downto 0);
+        O_wav      : out std_logic_vector(G_N-1 downto 0)
+        );
+end wave_generator;
+
+architecture arch of wave_generator is
+
+    constant C_addr_half_w : integer := integer(ceil(log2(real(natural(floor(G_fs/(4.0*G_f0)))))));
+
+    signal S_addr                 : std_logic_vector(integer(ceil(log2(real(natural(floor(G_fs/(2.0*G_f0))))))) - 1 downto 0);
+    signal S_sine_out_lut         : std_logic_vector(G_N-1 downto 0);
+    signal S_square               : std_logic_vector(G_N-1 downto 0);
+    signal S_triangle_out_lut     : std_logic_vector(G_N-1 downto 0);
+    signal S_saw_tooth_out_lut    : std_logic_vector(G_N-1 downto 0);
+    signal S_opposite_wave_sample : std_logic_vector(G_N-1 downto 0);
+    signal S_wave_value           : std_logic_vector(G_N-1 downto 0);
+    signal S_wave_sample          : std_logic_vector(G_N-1 downto 0);
+    signal S_last                 : std_logic;
+    signal S_middle               : std_logic;
+    signal S_u_d                  : std_logic;
+    signal S_sign_sel             : std_logic;
+
+begin
+    -- Module A
+    A_inst : entity work.module_A
+        port map (
+            I_clk      => I_clk,
+            I_rst      => I_rst,
+            I_wave_sel => I_wave_sel,
+            I_middle   => S_middle,
+            I_last     => S_last,
+            O_u_d      => S_u_d,
+            O_sign_sel => S_sign_sel
+            );
+
+    -- Module B
+    B_inst : entity work.module_B
+        generic map (
+            G_MAX_VAL => natural(floor(G_fs/(2.0*G_f0)))
+            )
+        port map (
+            I_clk    => I_clk,
+            I_rst    => I_rst,
+            I_u_d    => S_u_d,
+            O_val    => S_addr,
+            O_last   => S_last,
+            O_middle => S_middle 
+            );
+
+    -- Module C
+    C_inst : entity work.module_C
+        generic map (
+            G_N  => G_N,
+            G_f0 => G_f0,
+            G_fs => G_fs
+            )
+        port map (
+            I_clk  => I_clk,
+            I_rst  => I_rst,
+            I_addr => S_addr(C_addr_half_w-1 downto 0),
+            O_sine => S_sine_out_lut
+            );
+
+    -- Module D
+    D_inst : entity work.module_D
+        generic map (
+            G_N  => G_N,
+            G_f0 => G_f0,
+            G_fs => G_fs
+            )
+        port map (
+            I_clk      => I_clk,
+            I_rst      => I_rst,
+            I_addr     => S_addr(C_addr_half_w-1 downto 0),
+            O_triangle => S_triangle_out_lut
+            );
+
+    -- Module E
+    E_inst : entity work.module_E
+        generic map (
+            G_N  => G_N,
+            G_f0 => G_f0,
+            G_fs => G_fs
+            )
+        port map (
+            I_clk       => I_clk,
+            I_rst       => I_rst,
+            I_addr      => S_addr,
+            O_saw_tooth => S_saw_tooth_out_lut
+            );
+
+    S_square <= ((G_N-1) => '0', others => '1');
+
+    -- Module F
+    F_inst : entity work.module_F
+        port map (
+            I_sel  => I_wave_sel,
+            I_din0 => S_sine_out_lut,
+            I_din1 => S_square,
+            I_din2 => S_saw_tooth_out_lut,
+            I_din3 => S_triangle_out_lut,
+            O_dout => S_wave_sample
+            );
+
+    -- Module G
+    G_inst : entity work.module_G
+        generic map(
+            G_N => G_N
+            )
+        port map (
+            I_din  => S_wave_sample,
+            O_dout => S_opposite_wave_sample 
+            );
+
+    -- Module H
+    H_inst : entity work.module_H
+        port map (
+            I_sel  => S_sign_sel,
+            I_din0 => S_wave_sample,
+            I_din1 => S_opposite_wave_sample,
+            O_dout => S_wave_value
+            );
+
+    -- Module I
+    I_inst : entity work.module_I
+        generic map (
+            G_N => G_N
+            )
+        port map (
+            I_clk  => I_clk,
+            I_rst  => I_rst,
+            I_din  => S_wave_value,
+            O_dout => O_wav
+            );
+
+end arch;