目次

ファームウエア仕様検討

 H8のファームウエアを考える前に、CPLDの中に
 入れたい内容を、入れるだけ入れてみます。

 機能は、3つに分割します。

 画像処理を外して、2機能だけをCPLDに
 入れてみます。

 信号線を利用し、どんな制御をするかを
 考えます。



 GameBoyCameraの初期化は、H8が担当すると
 して、READ信号がHなってから、XCLKに同期
 して出力されるアナログ値Voutを、A/D変換
 します。

 A/D変換後、外部メモリにデータを保存します。
 CPLDにはA/D変換器を内蔵できない
 ので、A/D変換ICを用意します。

 メモリには、アドレスが必要なのでCPLDが
 READをトリガーとし、0から順次増やして
 いきます。

 トリガーを利用して、動作を制御するので
 シーケンサ(ステートマシン)を用意します。

 シーケンサの動作を考えます。
  1. START信号トリガー待ち、メモリアドレスクリア
  2. READ信号トリガー待ち
  3. SRAMのCSをイネーブルに(次のステートへ)
  4. XCLKにHを出力(次のステートへ)
  5. A/D変換のnWEをイネーブルに(次のステートへ)
  6. XCLKにLを出力、A/D変換のnWEをディセーブルに(次のステートへ)
  7. A/D変換終了待ち
  8. SRAMのnWRをイネーブルに(次のステートへ)
  9. メモリアドレスに+1、SRAMのnWRをディセーブルに(次のステートへ)
  10. メモリアドレスが8192なら次に、それ以外は4に
  11. SRAMのCSをディセーブルに(次のステートへ)
  12. はじめのステートにもどる
 上の処理を、VHDLコードにしてみます。 process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iSTATE <= 0 ; iMADR <= (others => '0') ; elsif rising_edge( iMCLK ) then case iSTATE is -- wait start trigger when 0 => if ( iSTART = '1' ) then iSTATE <= 1 ; iMADR <= (others => '0') ; elsif ( iZTRG = '1' ) then iSTATE <= 13 ; iMADR <= (others => '0') ; elsif ( iITRG = '1' ) then iSTATE <= 12 ; else iSTATE <= 0 ; end if ; -- wait read trigger when 1 => if ( iREAD = '1' ) then iSTATE <= 2 ; else iSTATE <= 1 ; end if ; -- enable chip select when 2 => iSTATE <= 3 ; -- XCLK : H when 3 => iSTATE <= 4 ; -- nADWE : L when 4 => iSTATE <= 5 ; -- XCLK : L / nADWE : H when 5 => iSTATE <= 6 ; -- wait nINTR when 6 => if ( iINTR = '1' ) then iSTATE <= 7 ; else iSTATE <= 6 ; end if ; -- enable nMWR when 7 => iSTATE <= 8 ; -- increment address when 8 => iSTATE <= 9 ; iMADR <= iMADR + '1' ; -- judge when 9 => if ( conv_integer(iMADR) = 0 ) then iSTATE <= 10 ; else iSTATE <= 3 ; end if ; -- disable chip select when 10 => iSTATE <= 11 ; -- return first state when 11 => iSTATE <= 0 ; -- increment when 12 => iSTATE <= 13 ; iMADR <= iMADR + '1' ; -- return first state when 13 => iSTATE <= 0 ; -- when others => iSTATE <= 0 ; end case ; end if ; end process ;  H8がSRAMのデータをリードするためにトリガーを利用し  アドレスを+1するか、ゼロクリアするかも含めます。  STARTトリガーを与えてから、GameBoyCameraの  XCLKは、CPLDから出力します。  シーケンサを定義してしまえば、トリガーを  生成するために、シフトレジスタを用意して  信号のエッジ変化を捉えます。 process(nRESET,iMCLK) begin if ( nRESET = '0' ) then iSTA_SFT <= "000" ; iREAD_SFT <= "000" ; iINTR_SFT <= "000" ; iZTRG_SFT <= "000" ; iITRG_SFT <= "000" ; elsif rising_edge( iMCLK ) then iSTA_SFT <= iSTA_SFT(1 downto 0) & START ; iREAD_SFT <= iREAD_SFT(1 downto 0) & XREAD ; iINTR_SFT <= iINTR_SFT(1 downto 0) & (not nINTR) ; iZTRG_SFT <= iZTRG_SFT(1 downto 0) & ZTRG ; iITRG_SFT <= iITRG_SFT(1 downto 0) & ITRG ; end if ; end process; iSTART <= '1' when ( iSTA_SFT = "011" or iSTA_SFT = "001" ) else '0' ; iREAD <= '1' when ( iREAD_SFT = "011" or iREAD_SFT = "001" ) else '0' ; iINTR <= '1' when ( iINTR_SFT = "011" or iINTR_SFT = "001" ) else '0' ; iZTRG <= '1' when ( iZTRG_SFT = "011" or iZTRG_SFT = "001" ) else '0' ; iITRG <= '1' when ( iITRG_SFT = "011" or iITRG_SFT = "001" ) else '0' ;  XCLKとA/D変換器ICのクロックは、次のように  生成します。  ADCLK <= iMCLK ; iSCLK <= '1' when ( iSTATE = 4 or iSTATE = 3 ) else '0' ;  A/D変換器関係信号とSRAM用のnMWRは、シーケンサの  状態変数を見て、論理値を確定します。 iADWE <= '1' when ( iSTATE = 4 ) else '0' ; iADRD <= '1' when ( 4 < iSTATE and iSTATE < 8 ) else '0' ; iMWR <= '1' when ( 1 < iSTATE and iSTATE < 10 ) else '0' ;  まとめると、次のようになります。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity mcrtstx is generic ( TOPX : integer := 2 ; XMAX : integer := 4 --; ); port ( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- camera interface (input) XCLK : in std_logic ; XRST : in std_logic ; SIN : in std_logic ; LOAD : in std_logic ; START : in std_logic ; XREAD : in std_logic ; -- camera interface (output) MXCLK : out std_logic ; MXRST : out std_logic ; MSIN : out std_logic ; MLOAD : out std_logic ; MSTART : out std_logic ; -- A/D converter interface ADCLK : out std_logic ; nADWR : out std_logic ; nADRD : out std_logic ; nINTR : in std_logic ; -- memory interface MADR : out std_logic_vector(12 downto 0) ; nMWR : out std_logic ; -- trigger ZTRG : in std_logic ; ITRG : in std_logic --; ); end mcrtstx; architecture behavioral of mcrtstx is -- component component clkgenx is generic ( TOPX : integer ; RMAX : integer --; ); port ( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- output CLKOUT : out std_logic -- ; ); end component ; -- internal clock signal iMCLK : std_logic ; signal iSCLK : std_logic ; -- shift register clock signal iSTA_SFT : std_logic_vector(2 downto 0) ; signal iREAD_SFT : std_logic_vector(2 downto 0) ; signal iINTR_SFT : std_logic_vector(2 downto 0) ; signal iZTRG_SFT : std_logic_vector(2 downto 0) ; signal iITRG_SFT : std_logic_vector(2 downto 0) ; signal iSTART : std_logic ; signal iREAD : std_logic ; signal iINTR : std_logic ; signal iZTRG : std_logic ; signal iITRG : std_logic ; -- sequencer signal iSTATE : integer range 0 to 15 ; signal iMADR : std_logic_vector(12 downto 0) ; signal iADWE : std_logic ; signal iADRD : std_logic ; signal iMWR : std_logic ; begin -- internal clock CLKX : clkgenx generic map (TOPX,XMAX) port map (nRESET,CLOCK,iMCLK) ; -- monitor output MXCLK <= iSCLK when ( iSTATE > 1 ) else XCLK ; MXRST <= XRST ; MSIN <= SIN ; MLOAD <= LOAD ; MSTART <= START ; -- trigger handling process(nRESET,iMCLK) begin if ( nRESET = '0' ) then iSTA_SFT <= "000" ; iREAD_SFT <= "000" ; iINTR_SFT <= "000" ; iZTRG_SFT <= "000" ; iITRG_SFT <= "000" ; elsif rising_edge( iMCLK ) then iSTA_SFT <= iSTA_SFT(1 downto 0) & START ; iREAD_SFT <= iREAD_SFT(1 downto 0) & XREAD ; iINTR_SFT <= iINTR_SFT(1 downto 0) & (not nINTR) ; iZTRG_SFT <= iZTRG_SFT(1 downto 0) & ZTRG ; iITRG_SFT <= iITRG_SFT(1 downto 0) & ITRG ; end if ; end process; iSTART <= '1' when ( iSTA_SFT = "011" or iSTA_SFT = "001" ) else '0' ; iREAD <= '1' when ( iREAD_SFT = "011" or iREAD_SFT = "001" ) else '0' ; iINTR <= '1' when ( iINTR_SFT = "011" or iINTR_SFT = "001" ) else '0' ; iZTRG <= '1' when ( iZTRG_SFT = "011" or iZTRG_SFT = "001" ) else '0' ; iITRG <= '1' when ( iITRG_SFT = "011" or iITRG_SFT = "001" ) else '0' ; -- A/D converter interface ADCLK <= iMCLK ; nADWR <= not iADWE ; nADRD <= not iADRD ; -- memory interface MADR <= iMADR ; nMWR <= not iMWR ; -- sequencer process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iSTATE <= 0 ; iMADR <= (others => '0') ; elsif rising_edge( iMCLK ) then case iSTATE is -- wait start trigger when 0 => if ( iSTART = '1' ) then iSTATE <= 1 ; iMADR <= (others => '0') ; elsif ( iZTRG = '1' ) then iSTATE <= 13 ; iMADR <= (others => '0') ; elsif ( iITRG = '1' ) then iSTATE <= 12 ; else iSTATE <= 0 ; end if ; -- wait read trigger when 1 => if ( iREAD = '1' ) then iSTATE <= 2 ; else iSTATE <= 1 ; end if ; -- enable chip select when 2 => iSTATE <= 3 ; -- XCLK : H when 3 => iSTATE <= 4 ; -- nADWE : L when 4 => iSTATE <= 5 ; -- XCLK : L / nADWE : H when 5 => iSTATE <= 6 ; -- wait nINTR when 6 => if ( iINTR = '1' ) then iSTATE <= 7 ; else iSTATE <= 6 ; end if ; -- enable nMWR when 7 => iSTATE <= 8 ; -- increment address when 8 => iSTATE <= 9 ; iMADR <= iMADR + '1' ; -- judge when 9 => if ( conv_integer(iMADR) = 0 ) then iSTATE <= 10 ; else iSTATE <= 3 ; end if ; -- disable chip select when 10 => iSTATE <= 11 ; -- return first state when 11 => iSTATE <= 0 ; -- increment when 12 => iSTATE <= 13 ; iMADR <= iMADR + '1' ; -- return first state when 13 => iSTATE <= 0 ; -- when others => iSTATE <= 0 ; end case ; end if ; end process ; iADWE <= '1' when ( iSTATE = 4 ) else '0' ; iADRD <= '1' when ( 4 < iSTATE and iSTATE < 8 ) else '0' ; iMWR <= '1' when ( 1 < iSTATE and iSTATE < 10 ) else '0' ; iSCLK <= '1' when ( iSTATE = 4 or iSTATE = 3 ) else '0' ; end behavioral;  信号ピンの割当ては、以下。 # system NET "nreset" LOC = "P74" ; NET "clock" LOC = "P9" ; # group A NET "XCLK" LOC = "P1" ; NET "XRST" LOC = "P2" ; NET "SIN" LOC = "P3" ; NET "LOAD" LOC = "P4" ; NET "START" LOC = "P5" ; NET "ZTRG" LOC = "P6" ; NET "ITRG" LOC = "P7" ; # NET "signal" LOC = "P10" ; # group B NET "XREAD" LOC = "P11" ; NET "MXCLK" LOC = "P12" ; NET "MXRST" LOC = "P13" ; NET "MSIN" LOC = "P14" ; NET "MLOAD" LOC = "P15" ; NET "MSTART" LOC = "P17" ; NET "ADCLK" LOC = "P18" ; NET "nADWR" LOC = "P19" ; # group C NET "nADRD" LOC = "P20" ; NET "nINTR" LOC = "P21" ; NET "nMWR" LOC = "P23" ; NET "MADR<12>" LOC = "P24" ; NET "MADR<11>" LOC = "P25" ; NET "MADR<10>" LOC = "P26" ; NET "MADR<9>" LOC = "P31" ; NET "MADR<8>" LOC = "P32" ; # group D NET "MADR<7>" LOC = "P33" ; NET "MADR<6>" LOC = "P34" ; NET "MADR<5>" LOC = "P35" ; NET "MADR<4>" LOC = "P36" ; NET "MADR<3>" LOC = "P37" ; NET "MADR<2>" LOC = "P39" ; NET "MADR<1>" LOC = "P40" ; NET "MADR<0>" LOC = "P41" ; (under construction)
目次

inserted by FC2 system