目次
前
次
最終VHDLコード
BCS(Bar Code Scanner)、モータ制御、マイクロ
コントローラに分割して、VHDLコードを説明する。
BCS(Bar Code Scanner)
BCSは、次の信号線で接続する。
- Vcc(5V)
- SH(START)
- φ1(CLKA)
- φ2(CLKB)
- Vout(DOS)
- GND
CLKA、CLKBは、論理和回路に接続しCLKABとする。
また、センサーデータは4ビットで出力する。
カウンタを2つ用意し、CLKABによりインクリメントする。
iSCNTは、START信号でリセットし、インクリメントする。
iSCNTXは、出力されてくるセンサーデータ数をカウント。
2カウンタの動作をタイミングチャートと整合するよう
VHDLコードを記述すると、以下となる。
process (nRESET,CLKAB)
begin
if ( nRESET = '0' ) then
iSCNT <= 0 ;
iSCNTX <= 0 ;
elsif rising_edge(CLKAB) then
-- total counter
if ( iSTART = '1' or iSCNT = SCNTMAX ) then
iSCNT <= 0 ;
else
iSCNT <= iSCNT + 1 ;
end if ;
-- sensing counter
if ( iSTART = '1' or iSCNT < SCNTFIRST ) then
iSCNTX <= 0 ;
else
iSCNTX <= iSCNTX + 1 ;
end if ;
end if ;
end process ;
iSCNTXを利用し、データ記憶のタイミングを決定。
iSTRG <= '1' when ( iSCNTX = SCNTLATCH0 ) else
'1' when ( iSCNTX = SCNTLATCH1 ) else
'1' when ( iSCNTX = SCNTLATCH2 ) else
'1' when ( iSCNTX = SCNTLATCH3 ) else
'1' when ( iSCNTX = SCNTLATCH4 ) else
'1' when ( iSCNTX = SCNTLATCH5 ) else
'1' when ( iSCNTX = SCNTLATCH6 ) else
'1' when ( iSCNTX = SCNTLATCH7 ) else
'0' ;
センサーデータを8ビットにすれば
MCRで作成したファームウエアを活用
できる。
データを記憶するためにシフトレジスタを利用。
process (nRESET,CLKAB)
begin
if ( nRESET = '0' ) then
iREG_SFT <= X"00" ;
elsif falling_edge(CLKAB) then
if ( iSTRG = '1' ) then
iREG_SFT <= iREG_SFT(6 downto 0) & iDOS ;
end if ;
end if ;
end process ;
1スキャンが終わり、データ更新されるまでは
センサーデータを保持しなくてはならないので
シーケンサでスキャン開始とデータ取得完了を
を監視する。
process (nRESET,CLOCK)
begin
if ( nRESET = '0' ) then
iSTATE <= "00" ;
iREG <= X"00" ;
elsif rising_edge(CLOCK) then
case conv_integer(iSTATE) is
-- wait trigger
when 0 => if ( iSTART_TRG = '1' ) then
iSTATE <= "01" ;
else
iSTATE <= "00" ;
end if ;
-- complete data store
when 1 => if ( iSCNT = SCNTFINE ) then
iSTATE <= "11" ;
else
iSTATE <= "01" ;
end if ;
-- copy
when 3 => iSTATE <= "10" ;
iREG <= iREG_SFT ;
-- return first state
when 2 => iSTATE <= "00" ;
-- default
when others =>
iSTATE <= "00" ;
end case ;
end if ;
end process ;
スキャン開始を検出するため、シンクロナイザを定義。
process (nRESET,CLKAB)
begin
if ( nRESET = '0' ) then
iSTART_SFT <= "000" ;
elsif rising_edge(CLKAB) then
iSTART_SFT <= iSTART_SFT(1 downto 0) & iSTART ;
end if ;
end process ;
iSTART_TRG <= '1' when ( iSTART_SFT = "011" ) else '0' ;
まとめると以下。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity tstbcs is
port (
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ;
-- BCS
START : in std_logic ;
CLKAB : in std_logic ;
DOS : in std_logic ;
-- selector
SEL : in std_logic ;
-- register output
REGOUT : out std_logic_vector(3 downto 0) --;
);
end tstbcs ;
architecture behavioral of tstbcs is
-- values
CONSTANT SCNTMAX : integer := 2081 ;
CONSTANT SCNTXMAX : integer := 2048 ;
CONSTANT SCNTFINE : integer := 2080 ;
CONSTANT SCNTFIRST : integer := 33 ;
-- latch location
CONSTANT SCNTLATCH0 : integer := 128 ;
CONSTANT SCNTLATCH1 : integer := 384 ;
CONSTANT SCNTLATCH2 : integer := 640 ;
CONSTANT SCNTLATCH3 : integer := 896 ;
CONSTANT SCNTLATCH4 : integer := 1152 ;
CONSTANT SCNTLATCH5 : integer := 1408 ;
CONSTANT SCNTLATCH6 : integer := 1664 ;
CONSTANT SCNTLATCH7 : integer := 1920 ;
-- BUS interface
signal iSTART : std_logic ;
signal iDOS : std_logic ;
-- internal counter
signal iSCNT : integer range 0 to SCNTMAX ;
signal iSCNTX : integer range 0 to SCNTXMAX ;
signal iSTRG : std_logic ;
-- synchronizer
signal iSTART_SFT : std_logic_vector(2 downto 0) ;
signal iSTART_TRG : std_logic ;
-- internal shift register
signal iREG_SFT : std_logic_vector(7 downto 0) ;
-- internal register
signal iSEL : std_logic ;
signal iREG : std_logic_vector(7 downto 0) ;
-- sequencer
signal iSTATE : std_logic_vector(1 downto 0) ;
begin
-- input
iSTART <= START ;
iDOS <= DOS ;
iSEL <= SEL ;
-- output
REGOUT <= iREG(7 downto 4) when ( iSEL = '1' ) else iREG(3 downto 0) ;
-- internal counter
process (nRESET,CLKAB)
begin
if ( nRESET = '0' ) then
iSCNT <= 0 ;
iSCNTX <= 0 ;
elsif rising_edge(CLKAB) then
-- total counter
if ( iSTART = '1' or iSCNT = SCNTMAX ) then
iSCNT <= 0 ;
else
iSCNT <= iSCNT + 1 ;
end if ;
-- sensing counter
if ( iSTART = '1' or iSCNT < SCNTFIRST ) then
iSCNTX <= 0 ;
else
iSCNTX <= iSCNTX + 1 ;
end if ;
end if ;
end process ;
iSTRG <= '1' when ( iSCNTX = SCNTLATCH0 ) else
'1' when ( iSCNTX = SCNTLATCH1 ) else
'1' when ( iSCNTX = SCNTLATCH2 ) else
'1' when ( iSCNTX = SCNTLATCH3 ) else
'1' when ( iSCNTX = SCNTLATCH4 ) else
'1' when ( iSCNTX = SCNTLATCH5 ) else
'1' when ( iSCNTX = SCNTLATCH6 ) else
'1' when ( iSCNTX = SCNTLATCH7 ) else
'0' ;
-- synchronizer
process (nRESET,CLKAB)
begin
if ( nRESET = '0' ) then
iSTART_SFT <= "000" ;
elsif rising_edge(CLKAB) then
iSTART_SFT <= iSTART_SFT(1 downto 0) & iSTART ;
end if ;
end process ;
iSTART_TRG <= '1' when ( iSTART_SFT = "011" ) else '0' ;
-- internal register
process (nRESET,CLKAB)
begin
if ( nRESET = '0' ) then
iREG_SFT <= X"00" ;
elsif falling_edge(CLKAB) then
if ( iSTRG = '1' ) then
iREG_SFT <= iREG_SFT(6 downto 0) & iDOS ;
end if ;
end if ;
end process ;
-- sequencer
process (nRESET,CLOCK)
begin
if ( nRESET = '0' ) then
iSTATE <= "00" ;
iREG <= X"00" ;
elsif rising_edge(CLOCK) then
case conv_integer(iSTATE) is
-- wait trigger
when 0 => if ( iSTART_TRG = '1' ) then
iSTATE <= "01" ;
else
iSTATE <= "00" ;
end if ;
-- complete data store
when 1 => if ( iSCNT = SCNTFINE ) then
iSTATE <= "11" ;
else
iSTATE <= "01" ;
end if ;
-- copy
when 3 => iSTATE <= "10" ;
iREG <= iREG_SFT ;
-- return first state
when 2 => iSTATE <= "00" ;
-- default
when others =>
iSTATE <= "00" ;
end case ;
end if ;
end process ;
end behavioral;
モータ制御
モータ制御は、5MHzクロックを入力し分周して
PWM波形生成のクロックにします。左右のDUTY比
を与えて、PWM波形を生成します。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity pout is
port (
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ; -- 5MHz
-- sensor handler
LEFTV : in std_logic_vector(6 downto 0) ;
RIGHTV : in std_logic_vector(6 downto 0) ;
-- pulse out
LPOUT : out std_logic ;
RPOUT : out std_logic --;
);
end pout ;
architecture behavioral of pout is
--
CONSTANT CNTMAX : integer := 499 ;
CONSTANT CNTHALF : integer := 250 ;
CONSTANT PCNTMAX : integer := 99 ;
-- counter
signal iPCNT : integer range 0 to 99 ;
signal iLEFTX : integer range 0 to 99 ;
signal iRIGHTX : integer range 0 to 99 ;
-- clock divider
signal iCNT : integer range 0 to CNTMAX ;
signal iPCLK : std_logic ;
begin
-- output
LPOUT <= '1' when ( iPCNT < iLEFTX ) else '0' ;
RPOUT <= '1' when ( iPCNT < iRIGHTX ) else '0' ;
-- clock divider (generate 10kHz)
process (nRESET,CLOCK)
begin
if ( nRESET = '0' ) then
iCNT <= 0 ;
elsif rising_edge(CLOCK) then
if ( iCNT = CNTMAX ) then
iCNT <= 0 ;
else
iCNT <= iCNT + 1 ;
end if ;
end if ;
end process ;
iPCLK <= '1' when ( iCNT < CNTHALF ) else '0' ;
-- counter
process (nRESET,iPCLK)
begin
if ( nRESET = '0' ) then
iPCNT <= 0 ;
iLEFTX <= 0 ;
iRIGHTX <= 0 ;
elsif rising_edge(iPCLK) then
if ( iPCNT = PCNTMAX ) then
iPCNT <= 0 ;
iLEFTX <= conv_integer(LEFTV) ;
iRIGHTX <= conv_integer(RIGHTV) ;
else
iPCNT <= iPCNT + 1 ;
end if ;
end if ;
end process ;
end behavioral;
マイクロコントローラ
マイクロコントローラのVHDLコードを備忘録として
記す前に、走行モードの状態遷移を確認します。
状態遷移を見れば、マイクロコントローラの動作で
不要な部分があるかも知れないとわかります。また
使わないレジスタも出てくることも。
走行モードは5状態あり、次の動作をさせます。
- IDLE その場で静止
- BLIND センサー情報を使わないで左右のDUTY比を変えて走行
- NORMAL センサー情報を使い、センターラインをトレース
- CRANK センサー情報を使い、クランクコースを走行
- LANE センサー情報を使い、車線変更
各状態遷移は、次のように設定。
IDLE→BLIND
スタートスイッチを押したなら、状態を
IDLEからBLINDにします。
状態遷移のトリガーは、スタートスイッチにします。
BLIND→NORMAL
BLINDでは、順を追って左右のDUTY比を変更します。
指定回DUTY比を変更後、NORMALに遷移します。
NORMAL→CRANK
NORMALモードで走行中、センターラインではなく
すべて白を検出したなら、CRANKモードに遷移します。
NORMAL→LANE
NORMALモードで走行中、センターラインではなく
片側によった白を検出したなら、LANEモードに
遷移します。
CRANK→NORMAL
CRANKモードで旋回中、センターラインを検出
したなら、NORMALモードに遷移します。
LANE→NORMAL
LANEモードですべて黒のコース面を移動中、センター
ラインを検出したなら、NORMALモードに遷移します。
(under constrcution)
目次
前
次