目次

同期検波用キャリアジェネレータ

 Software Defined Radio(SDR)を実現する場合
 IQ信号を生成します。IQ信号を生成しるために
 余弦波、正弦波の90度の位相差を持った信号が
 必要です。これらの信号を生成する回路を同期
 検波用キャリアジェネレータと呼びます。



 90度の位相差をつくるには、1波形(最大値N)を
 等分割し、初期値を0とN/4にして、波形値を取出
 していきます。



 CPLD/FPGAに格納する同期検波用キャリアジェネレータの
 ブロック図は、以下。



 1波形を(2^M-1)個の数値で表現し、デコーダに格納
 します。波形生成は、デコーダにカウント値を与える
 だけになります。

 1波形を256に分割し、波高値は127を中心に、0から255
 の範囲とします。

 デコーダで利用する数値は、ROMと似た定義にします。

 具体的には、次のように記述しました。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity xdec is
  port (
    -- address
    XADR : in  std_logic_vector(7 downto 0) ;
    -- data
    XOUT : out std_logic_vector(7 downto 0) -- ;
  ) ;
end xdec ;

architecture Behavioral of xdec is
  -- data type 
  type TROM is array(0 to 255) of std_logic_vector(7 downto 0);
  --
  CONSTANT CSROM : TROM := TROM'(
    X"7F", X"82", X"85", X"88", X"8B", X"8F", X"92", X"95",
    X"98", X"9B", X"9E", X"A1", X"A4", X"A7", X"AA", X"AD",
    X"B0", X"B2", X"B5", X"B8", X"BB", X"BE", X"C0", X"C3",
    X"C6", X"C8", X"CB", X"CD", X"D0", X"D2", X"D4", X"D7",
    X"D9", X"DB", X"DD", X"DF", X"E1", X"E3", X"E5", X"E7",
    X"E9", X"EA", X"EC", X"EE", X"EF", X"F0", X"F2", X"F3",
    X"F4", X"F5", X"F7", X"F8", X"F9", X"F9", X"FA", X"FB",
    X"FC", X"FC", X"FD", X"FD", X"FD", X"FE", X"FE", X"FE",
    X"FE", X"FE", X"FE", X"FE", X"FD", X"FD", X"FD", X"FC",
    X"FC", X"FB", X"FA", X"F9", X"F9", X"F8", X"F7", X"F5",
    X"F4", X"F3", X"F2", X"F0", X"EF", X"EE", X"EC", X"EA",
    X"E9", X"E7", X"E5", X"E3", X"E1", X"DF", X"DD", X"DB",
    X"D9", X"D7", X"D4", X"D2", X"D0", X"CD", X"CB", X"C8",
    X"C6", X"C3", X"C0", X"BE", X"BB", X"B8", X"B5", X"B2",
    X"B0", X"AD", X"AA", X"A7", X"A4", X"A1", X"9E", X"9B",
    X"98", X"95", X"92", X"8F", X"8B", X"88", X"85", X"82",
    X"7F", X"7C", X"79", X"76", X"73", X"6F", X"6C", X"69",
    X"66", X"63", X"60", X"5D", X"5A", X"57", X"54", X"51",
    X"4E", X"4C", X"49", X"46", X"43", X"40", X"3E", X"3B",
    X"38", X"36", X"33", X"31", X"2E", X"2C", X"2A", X"27",
    X"25", X"23", X"21", X"1F", X"1D", X"1B", X"19", X"17",
    X"15", X"14", X"12", X"10", X"0F", X"0E", X"0C", X"0B",
    X"0A", X"09", X"07", X"06", X"05", X"05", X"04", X"03",
    X"02", X"02", X"01", X"01", X"01", X"00", X"00", X"00",
    X"00", X"00", X"00", X"00", X"01", X"01", X"01", X"02",
    X"02", X"03", X"04", X"05", X"05", X"06", X"07", X"09",
    X"0A", X"0B", X"0C", X"0E", X"0F", X"10", X"12", X"14",
    X"15", X"17", X"19", X"1B", X"1D", X"1F", X"21", X"23",
    X"25", X"27", X"2A", X"2C", X"2E", X"31", X"33", X"36",
    X"38", X"3B", X"3E", X"40", X"43", X"46", X"49", X"4C",
    X"4E", X"51", X"54", X"57", X"5A", X"5D", X"60", X"63",
    X"66", X"69", X"6C", X"6F", X"73", X"76", X"79", X"7C"
  ) ;
begin
  -- output
  XOUT <= CSROM(conv_integer(XADR)) ;

end Behavioral;

 デコーダの数値は、Tcl/Tkスクリプトで生成しました。
 スクリプトの内容は以下。

set pi [expr 4 * atan(1)]
set xmul 127
set last 256
set tmp ""
for {set i 0} {$i < $last} {incr i} {
  # calculate phase
  set th [expr (2 * $pi * $i) / $last]
  # sine curve
  set xtmp [expr $xmul * (1+sin( $th ))]
  # convert integer
  set ytmp [format "%.0f" $xtmp]
  # convert hexadecimal
  set tmp "$tmp X\"[format "%02X" $ytmp]\","
  # show
  if { [expr $i % 8] == 7 } {
    puts $tmp
    set tmp ""
  }
}

 波形を生成するためのカウンタは、初期値を0か64と
 すればよいので、次のように定義しました。

  -- cosine counter
  process ( nRESET , CLOCK ) 
  begin
    if ( nRESET = '0' ) then
      iCREG <= X"40";
    elsif rising_edge( CLOCK ) then
      iCREG <= iCREG + '1' ;
    end if ;
  end process ;

  -- sine counter
  process ( nRESET , CLOCK ) 
  begin
    if ( nRESET = '0' ) then
      iSREG <= X"00";
    elsif rising_edge( CLOCK ) then
      iSREG <= iSREG + '1' ;
    end if ;
  end process ;

 デコーダは、component指定で取り込んで
 インスタンスで使います。

 全体のVHDLコードは、以下。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity fgen is
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- cosine output
    COUT : out std_logic_vector(7 downto 0) ;
    -- sine output
    SOUT : out std_logic_vector(7 downto 0) --;
  ) ;
end fgen;

architecture Behavioral of fgen is
  --
  component xdec 
    port (
      -- address
      XADR : in  std_logic_vector(7 downto 0) ;
      -- data
      XOUT : out std_logic_vector(7 downto 0) -- ;
    ) ;
  end component ;
  -- internal counter
  signal iCREG : std_logic_vector(7 downto 0) ;
  signal iSREG : std_logic_vector(7 downto 0) ;
  -- 
  signal iCOUT : std_logic_vector(7 downto 0) ;
  signal iSOUT : std_logic_vector(7 downto 0) ;
begin
  -- instance
  COSinst : xdec port map (
      -- address
      XADR => iCREG ,
      -- data
      XOUT => iCOUT
  ) ;

  SINinst : xdec port map (
      -- address
      XADR => iSREG ,
      -- data
      XOUT => iSOUT
  ) ;
  
  -- output
  COUT <= iCOUT ;
  SOUT <= iSOUT ;

  -- cosine counter
  process ( nRESET , CLOCK ) 
  begin
    if ( nRESET = '0' ) then
      iCREG <= X"40";
    elsif rising_edge( CLOCK ) then
      iCREG <= iCREG + '1' ;
    end if ;
  end process ;

  -- sine counter
  process ( nRESET , CLOCK ) 
  begin
    if ( nRESET = '0' ) then
      iSREG <= X"00";
    elsif rising_edge( CLOCK ) then
      iSREG <= iSREG + '1' ;
    end if ;
  end process ;

end Behavioral;

 CoolRunnerIIの最大マクロセル数256のチップに
 入れることができました。
 このチップのピンアサインは、次のように定義。

# system
NET "CLOCK"  LOC = "P22" ;
NET "nRESET" LOC = "P99" ;

# nibble inputs
NET "COUT<0>" LOC = "P6" ;
NET "COUT<1>" LOC = "P7" ;
NET "COUT<2>" LOC = "P8" ;
NET "COUT<3>" LOC = "P9" ;
NET "COUT<4>" LOC = "P10" ;
NET "COUT<5>" LOC = "P11" ;
NET "COUT<6>" LOC = "P12" ;
NET "COUT<7>" LOC = "P13" ;

# nibble outputs
NET "SOUT<0>" LOC = "P14" ;
NET "SOUT<1>" LOC = "P15" ;
NET "SOUT<2>" LOC = "P16" ;
NET "SOUT<3>" LOC = "P17" ;
NET "SOUT<4>" LOC = "P18" ;
NET "SOUT<5>" LOC = "P19" ;
NET "SOUT<6>" LOC = "P23" ;
NET "SOUT<7>" LOC = "P24" ;

 接続するクロックは、外部に用意したDDSで生成し
 D/Aコンバータは、R-2Rの抵抗で実現します。




 アナログとデジタルの橋渡しには、A/D、D/Aの
 変換器を利用しますが、抵抗とOPアンプを利用
 した簡易回路で充分な分野も多いことを覚えて
 おくと、役に立つ日がくるかも知れません。


目次

inserted by FC2 system