目次
前
次
ファームウエア仕様検討
H8のファームウエアを考える前に、CPLDの中に
入れたい内容を、入れるだけ入れてみます。
機能は、3つに分割します。
画像処理を外して、2機能だけをCPLDに
入れてみます。
信号線を利用し、どんな制御をするかを
考えます。
GameBoyCameraの初期化は、H8が担当すると
して、READ信号がHなってから、XCLKに同期
して出力されるアナログ値Voutを、A/D変換
します。
A/D変換後、外部メモリにデータを保存します。
CPLDにはA/D変換器を内蔵できない
ので、A/D変換ICを用意します。
メモリには、アドレスが必要なのでCPLDが
READをトリガーとし、0から順次増やして
いきます。
トリガーを利用して、動作を制御するので
シーケンサ(ステートマシン)を用意します。
シーケンサの動作を考えます。
- START信号トリガー待ち、メモリアドレスクリア
- READ信号トリガー待ち
- SRAMのCSをイネーブルに(次のステートへ)
- XCLKにHを出力(次のステートへ)
- A/D変換のnWEをイネーブルに(次のステートへ)
- XCLKにLを出力、A/D変換のnWEをディセーブルに(次のステートへ)
- A/D変換終了待ち
- SRAMのnWRをイネーブルに(次のステートへ)
- メモリアドレスに+1、SRAMのnWRをディセーブルに(次のステートへ)
- メモリアドレスが8192なら次に、それ以外は4に
- SRAMのCSをディセーブルに(次のステートへ)
- はじめのステートにもどる
上の処理を、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)
目次
前
次