-------------------------------------------------------------------------------- -- File Name: cnco.vhd -- Description: -- Complex Numerically Controlled Oscillator (CNCO) -- -- -- Designer: Scott Hoy (SDH) -- -- Revision History: -- 01/01/2011-SDH-Initial version created. -- -- -------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library devlib; use devlib.nco_pkg.iqrom; entity cnco is generic(Word_Size : positive := 16; Fraction_Size : natural := 15; Freq_Size : positive := 32; Phase_Size : positive := 10; Enable_Neg_Ejw : boolean := false; Enable_Freq_Adjust : boolean := false; Enable_Phase_Ports : boolean := false; Enable_Phase_Adjust : boolean := false); port( clk : in std_logic; rst : in std_logic := '0'; ce : in std_logic := '1'; finit : in std_logic_vector((Freq_Size-1) downto 0); fadj : in std_logic_vector((Freq_Size-1) downto 0); pinit : in std_logic_vector((Phase_Size-1) downto 0); padj : in std_logic_vector((Phase_Size-1) downto 0); o_re : out std_logic_vector((Word_Size-1) downto 0); o_im : out std_logic_vector((Word_Size-1) downto 0); o_ce : out std_logic ); end entity cnco; architecture rtl of cnco is signal addr : std_logic_vector((Phase_Size-1) downto 0) := (others => '0'); signal addr_ce : std_logic := '0'; signal w_re : std_logic_vector(o_re'range) := (others => '0'); signal w_im : std_logic_vector(o_im'range) := (others => '0'); signal w_ce : std_logic := '0'; begin o_re <= w_re; o_im <= w_im; o_ce <= w_ce; G1_T : if (Enable_Phase_Ports = true) generate begin G1_FF : if ((Enable_Freq_Adjust = false) and (Enable_Phase_Adjust = false)) generate constant PD_CE : positive := 2; signal qfreq : signed((Freq_Size-1) downto 0) := (others => '0'); signal qpinit : signed((Phase_Size-1) downto 0) := (others => '0'); signal qphase : signed((Phase_Size-1) downto 0) := (others => '0'); signal qce : std_logic_vector((PD_CE-1) downto 0) := (others => '0'); signal qacc : signed((Freq_Size-1) downto 0) := (others => '0'); signal qtheta : signed((Phase_Size-1) downto 0) := (others => '0'); signal qtheta_ce : std_logic := '0'; begin addr <= std_logic_vector(qtheta); addr_ce <= qtheta_ce; P1 : process(clk,rst) is begin if (rst = '1') then qfreq <= (others => '0'); qpinit <= (others => '0'); qphase <= (others => '0'); qce <= (others => '0'); qacc <= (others => '0'); qtheta <= (others => '0'); qtheta_ce <= '0'; elsif rising_edge(clk) then qfreq <= signed(finit); qpinit <= signed(pinit); qce <= qce((qce'high-1) downto qce'low) & ce; -- Note: qce(qce'high) will be time aligned with qacc and qphase. if (qce(qce'low) = '1') then qacc <= (qacc + qfreq); qphase <= qpinit; end if; qtheta <= (qacc(qacc'high downto (qacc'length-qtheta'length)) + qphase); qtheta_ce <= qce(qce'high); end if; end process P1; end generate G1_FF; G1_FT : if ((Enable_Freq_Adjust = false) and (Enable_Phase_Adjust = true)) generate constant PD_CE : positive := 2; signal qfreq : signed((Freq_Size-1) downto 0) := (others => '0'); signal qpinit : signed((Phase_Size-1) downto 0) := (others => '0'); signal qpadj : signed((Phase_Size-1) downto 0) := (others => '0'); signal qphase : signed((Phase_Size-1) downto 0) := (others => '0'); signal qce : std_logic_vector((PD_CE-1) downto 0) := (others => '0'); signal qacc : signed((Freq_Size-1) downto 0) := (others => '0'); signal qtheta : signed((Phase_Size-1) downto 0) := (others => '0'); signal qtheta_ce : std_logic := '0'; begin addr <= std_logic_vector(qtheta); addr_ce <= qtheta_ce; P1 : process(clk,rst) is begin if (rst = '1') then qfreq <= (others => '0'); qpinit <= (others => '0'); qpadj <= (others => '0'); qphase <= (others => '0'); qce <= (others => '0'); qacc <= (others => '0'); qtheta <= (others => '0'); qtheta_ce <= '0'; elsif rising_edge(clk) then qfreq <= signed(finit); qpinit <= signed(pinit); qpadj <= signed(padj); qce <= qce((qce'high-1) downto qce'low) & ce; -- Note: qce(qce'high) will be time aligned with qacc and qphase. if (qce(qce'low) = '1') then qacc <= (qacc + qfreq); qphase <= (qpinit + qpadj); end if; qtheta <= (qacc(qacc'high downto (qacc'length-qtheta'length)) + qphase); qtheta_ce <= qce(qce'high); end if; end process P1; end generate G1_FT; G1_TF : if ((Enable_Freq_Adjust = true) and (Enable_Phase_Adjust = false)) generate type signed_1d is array(natural range<>) of signed((Phase_Size-1) downto 0); constant PD_CE : positive := 3; constant NPREG : positive := 2; signal qfinit : signed((Freq_Size-1) downto 0) := (others => '0'); signal qfadj : signed((Freq_Size-1) downto 0) := (others => '0'); signal qfreq : signed((Freq_Size-1) downto 0) := (others => '0'); signal qpinit : signed_1d((NPREG-1) downto 0) := (others => (others => '0')); signal qphase : signed((Phase_Size-1) downto 0) := (others => '0'); signal qce : std_logic_vector((PD_CE-1) downto 0) := (others => '0'); signal qacc : signed((Freq_Size-1) downto 0) := (others => '0'); signal qtheta : signed((Phase_Size-1) downto 0) := (others => '0'); signal qtheta_ce : std_logic := '0'; begin addr <= std_logic_vector(qtheta); addr_ce <= qtheta_ce; P1 : process(clk,rst) is begin if (rst = '1') then qfinit <= (others => '0'); qfadj <= (others => '0'); qfreq <= (others => '0'); qpinit <= (others => (others => '0')); qphase <= (others => '0'); qce <= (others => '0'); qacc <= (others => '0'); qtheta <= (others => '0'); qtheta_ce <= '0'; elsif rising_edge(clk) then qfinit <= signed(finit); qfadj <= signed(fadj); qfreq <= (qfinit + qfadj); qpinit <= qpinit((qpinit'high-1) downto qpinit'low) & signed(pinit); qce <= qce((qce'high-1) downto qce'low) & ce; -- Note: qce(qce'high) will be time aligned with qacc and qphase. if (qce(qce'low+1) = '1') then qacc <= (qacc + qfreq); qphase <= qpinit(qpinit'high); end if; qtheta <= (qacc(qacc'high downto (qacc'length-qtheta'length)) + qphase); qtheta_ce <= qce(qce'high); end if; end process P1; end generate G1_TF; G1_TT : if ((Enable_Freq_Adjust = true) and (Enable_Phase_Adjust = true)) generate type signed_1d is array(natural range<>) of signed((Phase_Size-1) downto 0); constant PD_CE : positive := 3; constant NPREG : positive := 2; signal qfinit : signed((Freq_Size-1) downto 0) := (others => '0'); signal qfadj : signed((Freq_Size-1) downto 0) := (others => '0'); signal qfreq : signed((Freq_Size-1) downto 0) := (others => '0'); signal qpinit : signed_1d((NPREG-1) downto 0) := (others => (others => '0')); signal qpadj : signed_1d((NPREG-1) downto 0) := (others => (others => '0')); signal qphase : signed((Phase_Size-1) downto 0) := (others => '0'); signal qce : std_logic_vector((PD_CE-1) downto 0) := (others => '0'); signal qacc : signed((Freq_Size-1) downto 0) := (others => '0'); signal qtheta : signed((Phase_Size-1) downto 0) := (others => '0'); signal qtheta_ce : std_logic := '0'; begin addr <= std_logic_vector(qtheta); addr_ce <= qtheta_ce; P1 : process(clk,rst) is begin if (rst = '1') then qfinit <= (others => '0'); qfadj <= (others => '0'); qfreq <= (others => '0'); qpinit <= (others => (others => '0')); qpadj <= (others => (others => '0')); qphase <= (others => '0'); qce <= (others => '0'); qacc <= (others => '0'); qtheta <= (others => '0'); qtheta_ce <= '0'; elsif rising_edge(clk) then qfinit <= signed(finit); qfadj <= signed(fadj); qfreq <= (qfinit + qfadj); qpinit <= qpinit((qpinit'high-1) downto qpinit'low) & signed(pinit); qpadj <= qpadj((qpadj'high-1) downto qpadj'low) & signed(padj); qce <= qce((qce'high-1) downto qce'low) & ce; -- Note: qce(qce'high) will be time aligned with qacc and qphase. if (qce(qce'low+1) = '1') then qacc <= (qacc + qfreq); qphase <= (qpinit(qpinit'high) + qpadj(qpadj'high)); end if; qtheta <= (qacc(qacc'high downto (qacc'length-qtheta'length)) + qphase); qtheta_ce <= qce(qce'high); end if; end process P1; end generate G1_TT; end generate G1_T; G1_F : if (Enable_Phase_Ports = false) generate begin G1_F : if (Enable_Freq_Adjust = false) generate constant PD_CE : positive := 2; signal qfreq : signed((Freq_Size-1) downto 0) := (others => '0'); signal qce : std_logic_vector((PD_CE-1) downto 0) := (others => '0'); signal qacc : signed((Freq_Size-1) downto 0) := (others => '0'); signal qtheta : signed((Phase_Size-1) downto 0) := (others => '0'); signal qtheta_ce : std_logic := '0'; begin addr <= std_logic_vector(qtheta); addr_ce <= qtheta_ce; P1 : process(clk,rst) is begin if (rst = '1') then qfreq <= (others => '0'); qce <= (others => '0'); qacc <= (others => '0'); qtheta <= (others => '0'); qtheta_ce <= '0'; elsif rising_edge(clk) then qfreq <= signed(finit); qce <= qce((qce'high-1) downto qce'low) & ce; -- Note: qce(qce'high) will be time aligned with qacc and qphase. if (qce(qce'low) = '1') then qacc <= (qacc + qfreq); end if; qtheta <= qacc(qacc'high downto (qacc'length-qtheta'length)); qtheta_ce <= qce(qce'high); end if; end process P1; end generate G1_F; G1_T : if (Enable_Freq_Adjust = true) generate constant PD_CE : positive := 3; signal qfinit : signed((Freq_Size-1) downto 0) := (others => '0'); signal qfadj : signed((Freq_Size-1) downto 0) := (others => '0'); signal qfreq : signed((Freq_Size-1) downto 0) := (others => '0'); signal qce : std_logic_vector((PD_CE-1) downto 0) := (others => '0'); signal qacc : signed((Freq_Size-1) downto 0) := (others => '0'); signal qtheta : signed((Phase_Size-1) downto 0) := (others => '0'); signal qtheta_ce : std_logic := '0'; begin addr <= std_logic_vector(qtheta); addr_ce <= qtheta_ce; P1 : process(clk,rst) is begin if (rst = '1') then qfinit <= (others => '0'); qfadj <= (others => '0'); qfreq <= (others => '0'); qce <= (others => '0'); qacc <= (others => '0'); qtheta <= (others => '0'); qtheta_ce <= '0'; elsif rising_edge(clk) then qfinit <= signed(finit); qfadj <= signed(fadj); qfreq <= (qfinit + qfadj); qce <= qce((qce'high-1) downto qce'low) & ce; -- Note: qce(qce'high) will be time aligned with qacc and qphase. if (qce(qce'low+1) = '1') then qacc <= (qacc + qfreq); end if; qtheta <= qacc(qacc'high downto (qacc'length-qtheta'length)); qtheta_ce <= qce(qce'high); end if; end process P1; end generate G1_T; end generate G1_F; U1_ROM : component iqrom generic map(i_wl => addr'length, o_wl => Word_Size, o_fwl => Fraction_Size, Enable_Neg_Ejw => Enable_Neg_Ejw) port map( clk => clk, rst => rst, i => addr, i_ce => addr_ce, o_re => w_re, o_im => w_im, o_ce => w_ce ); end architecture rtl; configuration cfg_cnco of cnco is for rtl end for; end configuration cfg_cnco;