同期検波用キャリアジェネレータ
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アンプを利用
した簡易回路で充分な分野も多いことを覚えて
おくと、役に立つ日がくるかも知れません。
目次
前
次