-- -- Top level of a sine/cosine generator with a CORDIC implementation -- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity cordic_top is port ( clk : in std_logic; rst : in std_logic; ena : in std_logic; inc_angle : in std_logic_vector (7 downto 0); ticktime : in std_logic_vector (15 downto 0); gain_sin : in std_logic_vector (15 downto 0); gain_cos : in std_logic_vector (15 downto 0); offs_sin : in std_logic_vector (11 downto 0); offs_cos : in std_logic_vector (11 downto 0); angle : out std_logic_vector (14 downto 0); sinout : out std_logic_vector (15 downto 0); cosout : out std_logic_vector (15 downto 0) ); end; architecture rtl of cordic_top is signal s_inc_angle : signed (7 downto 0); signal s_sine, s_cosine : signed (15 downto 0); signal s_gainx, s_gainy : signed (15 downto 0); signal s_offx, s_offy : signed (11 downto 0); signal s_angle : signed (14 downto 0) := (others => '0'); signal done_i : std_logic; signal load_sr : std_logic_vector (31 downto 0) := x"0000_0001"; signal load_i : std_logic := '0'; signal tick : std_logic := '0'; signal tick_cnt : unsigned (15 downto 0) := (0 => '1', others => '0'); begin s_inc_angle <= signed (inc_angle); s_gainx <= signed (gain_cos); s_gainy <= signed (gain_sin); s_offx <= signed (offs_cos); s_offy <= signed (offs_sin); angle <= std_logic_vector (s_angle); sinout <= std_logic_vector (s_sine); cosout <= std_logic_vector (s_cosine); -- Create a 'tick' every desired 'ticktime'*10ns cycles proc_tick : process (clk) begin if rising_edge (clk) then if rst = '1' then tick <= '0'; elsif ena = '1' then tick_cnt <= tick_cnt + 1; tick <= '0'; if tick_cnt = unsigned (ticktime) then tick <= '1'; tick_cnt <= (0 => '1', others => '0'); end if; else tick <= '0'; end if; end if; end process; -- Update the angle with every tick by desired increment/decrement proc_angle : process (clk) begin if rising_edge (clk) then if rst = '1' then s_angle <= (others => '0'); elsif ena = '1' then if tick = '1' then s_angle <= s_angle + s_inc_angle; end if; else s_angle <= (others => '0'); end if; end if; end process; -- Trigger a new CORDIC calculation every 31 cycles (of 10ns) proc_load_sr : process (clk) begin if rising_edge (clk) then if rst = '1' then load_sr <= x"0000_0001"; elsif ena = '0' then load_sr <= x"0000_0001"; else load_sr <= load_sr (30 downto 0) & load_sr (31); end if; end if; end process; -- Start the CORDIC module to calculate new values for sine/cosine proc_load : process (clk) begin if rising_edge (clk) then if rst = '1' then load_i <= '0'; elsif ena = '1' then load_i <= load_sr (31); else load_i <= '0'; end if; end if; end process; -- CORDIC module mod_cordic : entity work.cordic port map ( clk => clk, -- FPGA clock rst => rst, -- Positive active synchronous reset clk_ena => '1', -- Clock enable for multicycle operation load => load_i, -- Start a new calculation gainx => s_gainx, -- Cordic gain ADC_X (cosine) gainy => s_gainy, -- Cordic gain ADC_Y (sine) off_x => s_offx, -- Offset to output signal x, must be zero for maximum gain off_y => s_offy, -- Offset to output signal y, must be zero for maximum gain phase => s_angle, -- Phase for which sine and cosine are calculated done => done_i, -- Indicate completion of calculation sinout => s_sine, -- The result, the sine component cosout => s_cosine -- The result, the cosine component ); end rtl;