メイン部分

VHDLメイン部分の構成は以下の通りになります。

・I/Oポート定義
・SRAM、CICコンポーネント定義
・ロータリエンコーダ処理
・SRAM読み出し、GPIO出力制御
・各種クロック生成
・SRAM書き込み制御
・CICフィルタ処理
・モニターPWM生成
・ユーザー定義LED

LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity ad9218 is port ( CLK : in std_logic; -- 50MHz master clock enca : out std_logic; -- AD9218 CK for chA encb : out std_logic; -- AD9218 CK for chB adi : in std_logic_vector(9 downto 0); -- AD9218 10bit bus adq : in std_logic_vector(9 downto 0); -- AD9218 10bit bus dat : out std_logic_vector(9 downto 0); -- GPIO 10bit bus sclk : in std_logic; -- GPIO sce : in std_logic; -- GPIO nwsw : in std_logic; -- GPIO mwsw : in std_logic; -- GPIO iqsw : in std_logic; -- GPIO msbsw : out std_logic; -- GPIO reia : in std_logic; -- Rotary Encoder Input A reib : in std_logic; -- Rotary Encoder Input B reoa : out std_logic; -- Rotary Encoder Output A reob : out std_logic; -- Rotary Encoder Output B gpioc : out std_logic; -- User defined GPIO_C gpiod : out std_logic; -- User defined GPIO_D gpioe : out std_logic; -- User defined GPIO_E gpiof : out std_logic; -- User defined GPIO_F led0 : out std_logic; -- LED Green led1 : out std_logic; -- LED Green led2 : out std_logic; -- LED Green led3 : out std_logic; -- LED Green led4 : out std_logic; -- LED Green led5 : out std_logic; -- LED Green led6 : out std_logic; -- LED Green led7 : out std_logic -- LED Green ); end ad9218; architecture ad of ad9218 is signal cnt : std_logic_vector(10 downto 0); signal ledi : std_logic_vector(7 downto 0); signal ledo : std_logic_vector(7 downto 0); signal b1i : std_logic_vector(9 downto 0); signal b1q : std_logic_vector(9 downto 0); signal b2i : std_logic_vector(9 downto 0); signal b2q : std_logic_vector(9 downto 0); signal b3i : std_logic_vector(9 downto 0); signal b3q : std_logic_vector(9 downto 0); signal b4i : std_logic_vector(9 downto 0); signal b4q : std_logic_vector(9 downto 0); signal cav: std_logic_vector(9 downto 0); signal acc: std_logic_vector(13 downto 0); signal ave: std_logic_vector(9 downto 0); signal boc: std_logic_vector(9 downto 0); signal pwc: std_logic_vector(7 downto 0); signal cmp: std_logic; signal pwm: std_logic; signal reta: std_logic; signal retb: std_logic; signal rea: std_logic; signal reb: std_logic; signal ck50m : std_logic; signal ck1r5m : std_logic; signal ck800k : std_logic; signal ck400k : std_logic; signal ck200k : std_logic; signal ck100k : std_logic; signal ck48k : std_logic; signal ck24k : std_logic; signal ckram : std_logic; signal ckmar : std_logic; signal cknar : std_logic; signal sout : std_logic; signal we : std_logic; signal wad : std_logic_vector(9 downto 0); -- SRAM address for Wide signal mad : std_logic_vector(9 downto 0); -- SRAM address for Mid signal nad : std_logic_vector(9 downto 0); -- SRAM address for Narrow signal rwe : std_logic; -- SRAM WE signal adw : std_logic_vector(9 downto 0); -- SRAM address signal adr : std_logic_vector(9 downto 0); -- SRAM address signal adrn: std_logic_vector(9 downto 0); -- SRAM address signal adrw: std_logic_vector(9 downto 0); -- SRAM address signal dii : std_logic_vector(9 downto 0); -- SRAM Data input signal doi : std_logic_vector(9 downto 0); -- SRAM Data output signal diq : std_logic_vector(9 downto 0); -- SRAM Data input signal doq : std_logic_vector(9 downto 0); -- SRAM Data output component ram1 port ( clock: IN STD_LOGIC; data: IN STD_LOGIC_VECTOR (9 DOWNTO 0); write_address: IN INTEGER RANGE 0 to 1023; read_address: IN INTEGER RANGE 0 to 1023; we: IN STD_LOGIC; q: OUT STD_LOGIC_VECTOR (9 DOWNTO 0) ); end component; component cic generic( m:integer ); port( CKin1 : in std_logic; CKin2 : in std_logic; fin : in std_logic_vector(9 downto 0); fout : out std_logic_vector(9 downto 0) ); end component; begin ------------------------ Rotary Encoder process(reia, reib) begin if reia'event and reia = '1' then if reib = '0' then reta <= '1'; retb <= '0'; elsif reib = '1' then reta <= '0'; retb <= '1'; end if; end if; end process; rea <= reta and reia; reb <= retb and reia; reoa <= rea; reob <= reb; ------------------------ DATA output for Wide or Mid process(sclk, sce) begin if sce = '0' then adrw <= "1111111111"; elsif sclk'event and sclk = '1' then adrw <= adrw + '1'; end if; end process; ------------------------ DATA output for Narrow process(sclk, sce, nad(9), iqsw) begin if sce = '0' then if nad(9)='0' then -- Writing RAM 0-511 adrn <= "1000000000"; -- Read Ich 512-1023 elsif nad(9)='1' then -- Writing RAM 512-1023 adrn <= "0000000000"; -- Read Ich 0-511 end if; elsif sclk'event and sclk = '0' then adrn <= adrn + '1'; end if; end process; adr <= adrw when nwsw='1' else adrn; dat <= doi when iqsw='1' else doq when iqsw='0'; ------------------------ Make Encode A&B process(CLK) begin if CLK'event and CLK = '1' then cnt <= cnt + '1'; end if; end process; ck50m <= CLK; ck1r5m <= cnt(4); ck800k <= cnt(5); ck400k <= cnt(6); ck200k <= cnt(7); ck100k <= cnt(8); ck48k <= cnt(9); ck24k <= cnt(10); ckmar <= ck1r5m; -- Mid CK cknar <= ck48k; -- Narrow CK enca <= ck50m; encb <= ck50m; ------------------------ Generate SRAM address for Wide process(ck50m, sce) begin if sce = '1' then wad <= "0000000000"; elsif ck50m'event and ck50m = '1' and wad < "1111111111" then wad <= wad + '1'; end if; end process; ------------------------ Generate SRAM address for Mid process(ckmar, sce) begin if sce = '1' then mad <= "0000000000"; elsif ckmar'event and ckmar = '1' and mad < "1111111111" then mad <= mad + '1'; end if; end process; ------------------------ Generate SRAM address for Narrow process(cknar) begin if cknar'event and cknar = '1' then nad <= nad + '1'; end if; end process; we <= '1'; b1i <= adi; b1q <= adq; ------------------------ Mux Address Bus adw <= wad when nwsw = '1' and mwsw = '0' else mad when nwsw = '1' and mwsw = '1' else nad; ------------------------ Mux Data Bus dii <= b1i when nwsw = '1' and mwsw = '0' else b2i when nwsw = '1' and mwsw = '1' else b3i; diq <= b1q when nwsw = '1' and mwsw = '0' else b2q when nwsw = '1' and mwsw = '1' else b3q; ------------------------ Mux CLK for RAM ckram <= ck50m when sce='0' and nwsw = '1' and mwsw = '0' else -- Write Wide band ckmar when sce='0' and nwsw = '1' and mwsw = '1' else -- Write Mid band cknar when sce='0' and nwsw = '0' else -- Write Narr band sclk when sce='1'; -- Read GPIO ------------------------ RAM block 8bit x 1024 r1: ram1 port map(clock => ckram, data => dii, write_address => conv_integer(adw), read_address => conv_integer(adr), we => we, q => doi ); ------------------------ RAM block 8bit x 1024 r2: ram1 port map(clock => ckram, data => diq, write_address => conv_integer(adw), read_address => conv_integer(adr), we => we, q => doq ); -- CIC filter function 50M -> 1/32 -> 1.56Msps Gain 15dB u1: CIC generic map(m => 15) port map(CKin1 => ck50m, CKin2 => ck1r5m, fin => b1i, fout => b2i); u2: CIC generic map(m => 15) port map(CKin1 => ck50m, CKin2 => ck1r5m, fin => b1q, fout => b2q); -- CIC filter function 1.56Msps -> 1/32 -> 48ksps Gain 15dB u3: CIC generic map(m => 15) port map(CKin1 => ck1r5m, CKin2 => ck48k, fin =>b2i, fout => b3i); u4: CIC generic map(m => 15) port map(CKin1 => ck1r5m, CKin2 => ck48k, fin =>b2q, fout => b3q); -- Convert 10bit signed to 10bit unsigned boc <= b2i + "1000000000"; -- Averaging to remove DC offset process(ck400k) begin if ck400k'event and ck400k='1' then acc <= cav * "0111" + boc; -- 7/8 + 1/8 cav <= acc(12 downto 3); -- div by 8 ave <= cav; end if; end process; -- Convert Wave to Pulse cmp <= '1' when boc>ave else '0'; -- Make constant Mark and variable Space process(ck50m) begin if cmp='0' then pwc <= "00000000"; elsif ck50m'event and ck50m='1' and pwc < "11100000" then pwc <= pwc + '1'; end if; end process; msbsw <= nad(9); -- Convert Pulse to PWM pwm <= '1' when pwc > "00000000" and pwc <"01111111" else '0'; gpioc <= pwm; ------------------------ LED led0 <= '0'; led1 <= '1'; led2 <= '0'; led3 <= '0'; led4 <= '0'; led5 <= '0'; led6 <= '0'; led7 <= pwm; end ad;


CIC部分

このCICを2段使用しています。
CICフィルタを通すことでビット幅が拡大しますが、以下の式で求められます。

Bout = N × log2(R) + Bin
= 4 × log2(32) + 10 = 30(bit)

CICフィルタの仕様は以下になります。

デシメーションレート:R=CKin1/CKin2 で定義可能
タップ数:N = 4
入力ビット幅:Bin = 10bit
出力ビット幅:Bout = 10bit  ←拡大した30bitから10bitだけ取り出し
ゲイン:変数 m の値でゲインを定義可能

m=14 : 18dB
m=15 : 15dB
m=16 : 12dB

IBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_signed.all; entity cic is generic( m:integer ); port ( CKin1 : in std_logic; CKin2 : in std_logic; fin : in std_logic_vector(9 downto 0); fout : out std_logic_vector(9 downto 0) ); end cic; architecture ad of cic is constant N: integer :=40; signal cnt : std_logic_vector(9 downto 0) := "0000000000"; signal b0 : std_logic_vector(N downto 0); signal b1 : std_logic_vector(N downto 0); signal b2 : std_logic_vector(N downto 0); signal b3 : std_logic_vector(N downto 0); signal b4 : std_logic_vector(N downto 0); signal b5 : std_logic_vector(N downto 0); signal b6 : std_logic_vector(N downto 0); signal b7 : std_logic_vector(N downto 0); signal b8 : std_logic_vector(N downto 0); signal z0 : std_logic_vector(N downto 0); signal z1 : std_logic_vector(N downto 0); signal z2 : std_logic_vector(N downto 0); signal z3 : std_logic_vector(N downto 0); signal z4 : std_logic_vector(N downto 0); signal z5 : std_logic_vector(N downto 0); signal z6 : std_logic_vector(N downto 0); signal z7 : std_logic_vector(N downto 0); signal z8 : std_logic_vector(N downto 0); signal v0 : std_logic_vector(N downto 0) := "00000000000000000000000000000000000000000"; begin ------------------------ CIC Integral filter process(CKin1) begin if CKin1'event and CKin1='1' then b1 <= z1 + fin; b2 <= z2 + b1; b3 <= z3 + b2; b4 <= z4 + b3; z1 <= b1; z2 <= b2; z3 <= b3; z4 <= b4; end if; end process; process(CKin2) begin if CKin2'event and CKin2='0' then b5 <= b4 - z5; b6 <= b5 - z6; b7 <= b6 - z7; b8 <= b7 - z8; z5 <= b4; z6 <= b5; z7 <= b6; z8 <= b7; end if; end process; fout <= b8(m+9 downto m); -- Variable Gain end ad;


SRAM部分

SRAMの仕様は以下になります。

・ビット幅:10bit
・サイズ:1024 × 10bit
・同時読出・書込可能

LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY ram1 IS PORT ( clock:      IN STD_LOGIC; data:       IN STD_LOGIC_VECTOR (9 DOWNTO 0); write_address:  IN INTEGER RANGE 0 to 1023; read_address:  IN INTEGER RANGE 0 to 1023; we:        IN STD_LOGIC; q:         OUT STD_LOGIC_VECTOR (9 DOWNTO 0) ); END ram1; ARCHITECTURE rtl OF ram1 IS TYPE MEM IS ARRAY(0 TO 1023) OF STD_LOGIC_VECTOR(9 DOWNTO 0); SIGNAL ram_block: MEM; BEGIN PROCESS (clock) BEGIN IF (clock'event AND clock = '1') THEN IF (we = '1') THEN ram_block(write_address) <= data; END IF; q <= ram_block(read_address); END IF; END PROCESS; END rtl;