-------------------------------------------------------------------------------- -- File Name: iqrom.vhd -- Description: -- I/Q Read-Only Memory (ROM) -- -- -- 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; use ieee.math_real.all; library ieee_proposed; use ieee_proposed.math_utility_pkg.all; use ieee_proposed.fixed_pkg.all; entity iqrom is generic(i_wl : positive := 10; o_wl : positive := 16; o_fwl : natural := 15; Enable_Neg_Ejw : boolean := false); port( clk : in std_logic; rst : in std_logic := '0'; i : in std_logic_vector((i_wl-1) downto 0); i_ce : in std_logic := '1'; o_re : out std_logic_vector((o_wl-1) downto 0); o_im : out std_logic_vector((o_wl-1) downto 0); o_ce : out std_logic ); end entity iqrom; architecture rtl of iqrom is type array1d is array(natural range<>) of signed((o_wl-1) downto 0); function to_signed(arg : real; wl : positive; fwl : natural) return signed is constant lhs : integer := (wl-fwl-1); constant rhs : integer := (-fwl); variable q_sf : sfixed(lhs downto rhs) := (others => '0'); variable result : signed((wl-1) downto 0) := (others => '0'); begin q_sf := to_sfixed(arg,q_sf'high,q_sf'low,fixed_saturate,fixed_round); result := signed(to_slv(q_sf)); return result; end function to_signed; function negate(arg : std_logic_vector; arg_fwl : natural; size : positive) return std_logic_vector is constant lhs : integer := (arg'length-arg_fwl-1); constant rhs : integer := (-arg_fwl); variable arg_sf : sfixed(lhs downto rhs) := (others => '0'); variable neg_sf : sfixed(lhs downto rhs) := (others => '0'); variable neg_slv : std_logic_vector(arg'range) := (others => '0'); variable result : std_logic_vector((size-1) downto 0) := (others => '0'); begin arg_sf := to_sfixed(arg,arg_sf'high,arg_sf'low); neg_sf := resize((-arg_sf),neg_sf'high,neg_sf'low,fixed_saturate,fixed_truncate); neg_slv := to_slv(neg_sf); result := std_logic_vector(resize(signed(neg_slv),result'length)); return result; end function negate; function iqTable(nWords : positive; phase_wl : positive; wl : positive; fwl : natural) return array1d is constant step : real := 1.0/real(2**(phase_wl)); variable t, f, wt, x : real := 0.0; variable qx : signed((wl-1) downto 0) := (others => '0'); variable result : array1d((nWords-1) downto 0) := (others => (others => '0')); begin ---------------------------------------------------------------------------- -- This function will generate one-quarter of a cosine (I). ---------------------------------------------------------------------------- t := 0.0; f := 1.0; for k in result'low(1) to result'high(1) loop wt := (math_2_pi*f*t); x := cos(wt); qx := to_signed(x,qx'length,fwl); result(k) := qx; t := t + step; end loop; return result; end function iqTable; constant NWORDS : positive := 2**(abs(i_wl-2)); constant OFFSET : natural := (((2**i_wl)/4)-1); constant IQROM : array1d((NWORDS-1) downto 0) := iqTable(NWORDS,i_wl,o_wl,o_fwl); constant CTRL_WL : positive := 2; constant ADDR_WL : positive := (i_wl-CTRL_WL); constant PD_CTRL : positive := 2; constant PD_CE : positive := (PD_CTRL+1); type ctrl_1d is array(natural range<>) of unsigned((CTRL_WL-1) downto 0); signal rom : array1d((NWORDS-1) downto 0) := IQROM; signal ctrl : unsigned((CTRL_WL-1) downto 0) := (others => '0'); signal qi : unsigned(i'range) := (others => '0'); signal qctrl : ctrl_1d((PD_CTRL-1) downto 0):= (others => (others => '0')); signal qaddr_i : unsigned((ADDR_WL-1) downto 0) := (others => '0'); signal qaddr_q : unsigned((ADDR_WL-1) downto 0) := (others => '0'); signal qcos : signed(o_re'range) := (others => '0'); signal qsin : signed(o_im'range) := (others => '0'); signal qce : std_logic_vector((PD_CE-1) downto 0) := (others => '0'); signal re : std_logic_vector(o_re'range) := (others => '0'); signal im : std_logic_vector(o_im'range) := (others => '0'); ---------------------------------------------------------------------- -- Altera Synthesis Attribute ---------------------------------------------------------------------- -- romstyle string values: -- "M512"|"M4K"|"M-RAM"|"MLAB"|"M9K"|"M144K"|"LOGIC"|"AUTO" attribute romstyle : string; attribute romstyle of rom : signal is "AUTO"; ---------------------------------------------------------------------- ---------------------------------------------------------------------- -- Synplicity Synthesis Attribute ---------------------------------------------------------------------- -- syn_romstyle string values: "logic" | "block_rom" | "lpm_rom" --attribute syn_romstyle : string; --attribute syn_romstyle of rom : signal is "block_rom"; ---------------------------------------------------------------------- begin o_re <= re; o_im <= im; o_ce <= qce(qce'high); P_Rom : process(clk) is begin if rising_edge(clk) then qcos <= rom(to_integer(qaddr_i)); qsin <= rom(to_integer(qaddr_q)); end if; end process P_Rom; ctrl <= qi(qi'high downto (qi'length-ctrl'length)); P1 : process(clk,rst) is begin if (rst = '1') then qi <= (others => '0'); qctrl <= (others => (others => '0')); qaddr_i <= (others => '0'); qaddr_q <= (others => '0'); qce <= (others => '0'); elsif rising_edge(clk) then qi <= unsigned(i); qctrl <= qctrl((qctrl'high-1) downto qctrl'low) & ctrl; qce <= qce((qce'high-1) downto qce'low) & i_ce; case ctrl is when "00" => qaddr_i <= qi(qaddr_i'high downto qaddr_i'low); qaddr_q <= (to_unsigned(OFFSET,qaddr_q'length) - qi(qaddr_q'high downto qaddr_q'low)); when "01" => qaddr_i <= (to_unsigned(OFFSET,qaddr_i'length) - qi(qaddr_i'high downto qaddr_i'low)); qaddr_q <= qi(qaddr_q'high downto qaddr_q'low); when "10" => qaddr_i <= qi(qaddr_i'high downto qaddr_i'low); qaddr_q <= (to_unsigned(OFFSET,qaddr_q'length) - qi(qaddr_q'high downto qaddr_q'low)); when "11" => qaddr_i <= (to_unsigned(OFFSET,qaddr_i'length) - qi(qaddr_i'high downto qaddr_i'low)); qaddr_q <= qi(qaddr_q'high downto qaddr_q'low); when others => null; end case; end if; end process P1; G_ENE_T : if (Enable_Neg_Ejw = true) generate -- Generate e^(-jwt) = cos(wt) - j*sin(wt) where j = sqrt(-1). signal qre : signed(qcos'range) := (others => '0'); signal qim : signed(qsin'range) := (others => '0'); begin re <= std_logic_vector(qre); im <= std_logic_vector(qim); P1 : process(clk,rst) is begin if (rst = '1') then qre <= (others => '0'); qim <= (others => '0'); elsif rising_edge(clk) then case qctrl(qctrl'high) is when "00" => qre <= qcos; qim <= -qsin; when "01" => qre <= -qcos; qim <= -qsin; when "10" => qre <= -qcos; qim <= qsin; when "11" => qre <= qcos; qim <= qsin; when others => null; end case; end if; end process P1; end generate G_ENE_T; G_ENE_F : if (Enable_Neg_Ejw = false) generate -- Generate e^(jwt) = cos(wt) + j*sin(wt) where j = sqrt(-1). signal qre : signed(qcos'range) := (others => '0'); signal qim : signed(qsin'range) := (others => '0'); begin re <= std_logic_vector(qre); im <= std_logic_vector(qim); P1 : process(clk,rst) is begin if (rst = '1') then qre <= (others => '0'); qim <= (others => '0'); elsif rising_edge(clk) then case qctrl(qctrl'high) is when "00" => qre <= qcos; qim <= qsin; when "01" => qre <= -qcos; --negate(qcos,o_fwl,qre'length); -- -qcos; qim <= qsin; when "10" => qre <= -qcos; --negate(qcos,o_fwl,qre'length); -- -qcos; qim <= -qsin; --negate(qsin,o_fwl,qim'length); -- -qsin; when "11" => qre <= qcos; qim <= -qsin; --negate(qsin,o_fwl,qim'length); -- -qsin; when others => null; end case; end if; end process P1; end generate G_ENE_F; end architecture rtl; configuration cfg_iqrom of iqrom is for rtl end for; end configuration cfg_iqrom;