目次
前
次
8LED方向指示器作成
8LEDを利用して、左右の方向指示器を
作成してみます。
8個のLEDを横一列に並べて、左右それぞれ
4個を使い、点滅させます。
LED基板は、次の基板を使います。
左右の方向指示なので、点灯パターンを考えて
それをVHDLコードに変換。
左方向指示
中央から左にむけて、LEDを点灯。
右方向指示
中央から右にむけて、LEDを点灯。
点灯は0から4の5状態になっているので
5進数カウンタがあるとして、デコードで
左右の点灯を決定。
デコーダをVHDLコードで記述してみます。
左方向指示
デコーダ出力は、他の部位からの指示で
LEDに転送するとしておきます。
-- output
Lout <= iLout when ( ??? ) else X"0" ;
-- decode
iLout <= X"1" when ( iSCNT = 1 ) else
X"3" when ( iSCNT = 2 ) else
X"7" when ( iSCNT = 3 ) else
X"F" when ( iSCNT = 4 ) else
X"0" ;
右方向指示
他の部位からの指示で、デコード出力を
LEDに転送と仮定。
-- output
Rout <= iRout when ( ??? ) else X"0" ;
-- decode
iRout <= X"8" when ( iSCNT = 1 ) else
X"C" when ( iSCNT = 2 ) else
X"E" when ( iSCNT = 3 ) else
X"F" when ( iSCNT = 4 ) else
X"0" ;
デコーダは、シーケンサの出力値iSCNTで
値を決めているので、バイナリカウンタ
を利用して記述できます。
-- binary counter
process (nRESET,iBCLK)
begin
if ( nRESET = '0' ) then
iSCNT <= 0 ;
elsif rising_edge(iBCLK) then
if ( iSCNT = 4 ) then
iSCNT <= 0 ;
else
iSCNT <= iSCNT + 1 ;
end if ;
end if ;
end process ;
カウンタを動かすには、クロックが必要なので
マスタークロックからシーケンサとカウンタの
ためのクロックを生成。
ブロック図からVHDLコードを作成。
-- divider
process ( nRESET , CLOCK )
begin
if ( nRESET = '0' ) then
iACNT <= 0 ;
elsif rising_edge( CLOCK ) then
if ( iACNT = ACNT_MAX ) then
iACNT <= 0 ;
else
iACNT <= iACNT + 1 ;
end if ;
end if ;
end process ;
iACLK <= '1' when ( iACNT < ACNT_HALF ) else '0' ;
process ( nRESET , iACLK )
begin
if ( nRESET = '0' ) then
iBCNT <= 0 ;
elsif rising_edge( iACLK ) then
if ( iBCNT = BCNT_MAX ) then
iBCNT <= 0 ;
else
iBCNT <= iBCNT + 1 ;
end if ;
end if ;
end process ;
iBCLK <= '1' when ( iBCNT < BCNT_HALF ) else '0' ;
方向を指示するには、ボタンを利用。
回路は、次のようになっているとします。
ボタンには、チャタリングがあるので
シフトレジスタを使って除去しておき
シーケンサにトリガーを与えます。
iLTRG <= '1' when ( iLSFT = "01" ) else '0' ;
iRTRG <= '1' when ( iRSFT = "01" ) else '0' ;
process( nRESET , iACLK )
begin
if ( nRESET = '0' ) then
iLSFT <= "00" ;
iRSFT <= "00" ;
elsif rising_edge( iACLK ) then
iLSFT <= iLSFT(0) & LSWT ;
iRSFT <= iRSFT(0) & RSWT ;
end if ;
end process;
トリガーを受けたなら、15秒間だけ
LEDに点灯パターンを出力することに
します。
シーケンサの状態遷移は、以下。
状態遷移図を2ビットのジョンソンカウンタを
ベースにして、VHDLコードに変換。
-- sequencer
process( nRESET , iACLK )
begin
if ( nRESET = '0' ) then
iSTATE <= "00" ;
iWCNT <= 0 ;
elsif rising_edge( iACLK ) then
case conv_integer(iSTATE) is
-- wait trigger
when 0 => if ( iLTRG = '1' or iRTRG = '1' ) then
iSTATE <= "01" ;
else
iSTATE <= "00" ;
end if ;
-- enable and set counter
when 1 => iSTATE <= "11" ;
iWCNT <= 15000 ;
-- wait and decrement
when 3 => if ( iWCNT = 0 ) then
iSTATE <= "10" ;
else
iSTATE <= "11" ;
iWCNT <= iWCNT - 1 ;
end if ;
-- disable and return first state
when 2 => iSTATE <= "00" ;
-- default
when others => iSTATE <= "00" ;
end case ;
end if ;
end process;
まとめます。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity dflash is
Port (
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ; -- 4MHz
-- clock monitor
ACLK : out std_logic ;
BCLK : out std_logic ;
-- button inputs
LSWT : in std_logic ;
RSWT : in std_logic ;
-- output
Lout : out std_logic_vector(3 downto 0) ;
Rout : out std_logic_vector(3 downto 0) --;
);
end dflash;
architecture Behavioral of dflash is
--
CONSTANT ACNT_MAX : integer := 3999 ;
CONSTANT BCNT_MAX : integer := 999 ;
CONSTANT ACNT_HALF : integer := 2000 ;
CONSTANT BCNT_HALF : integer := 500 ;
CONSTANT LAST : integer := 15000 ;
-- divider
signal iACNT : integer range 0 to ACNT_MAX ;
signal iACLK : std_logic ;
signal iBCNT : integer range 0 to BCNT_MAX ;
signal iBCLK : std_logic ;
-- synchronizer
signal iLSFT : std_logic_vector(1 downto 0) ;
signal iRSFT : std_logic_vector(1 downto 0) ;
signal iLTRG : std_logic ;
signal iRTRG : std_logic ;
-- decoder
signal iLout : std_logic_vector(3 downto 0) ;
signal iRout : std_logic_vector(3 downto 0) ;
signal iSCNT : integer range 0 to 4 ;
-- sequencer
signal iSTATE : std_logic_vector(1 downto 0) ;
signal iWCNT : integer range 0 to LAST ;
begin
-- output
Lout <= iLout when ( iSTATE = "11" ) else X"0" ;
Rout <= iRout when ( iSTATE = "11" ) else X"0" ;
-- left decode
iLout <= X"1" when ( iSCNT = 1 ) else
X"3" when ( iSCNT = 2 ) else
X"7" when ( iSCNT = 3 ) else
X"F" when ( iSCNT = 4 ) else
X"0" ;
-- right decode
iRout <= X"8" when ( iSCNT = 1 ) else
X"C" when ( iSCNT = 2 ) else
X"E" when ( iSCNT = 3 ) else
X"F" when ( iSCNT = 4 ) else
X"0" ;
-- monitor
ACLK <= iACLK ;
BCLK <= iBCLK ;
-- binary counter
process (nRESET,iBCLK)
begin
if ( nRESET = '0' ) then
iSCNT <= 0 ;
elsif rising_edge(iBCLK) then
if ( iSCNT = 4 ) then
iSCNT <= 0 ;
else
iSCNT <= iSCNT + 1 ;
end if ;
end if ;
end process ;
-- divider
process ( nRESET , CLOCK )
begin
if ( nRESET = '0' ) then
iACNT <= 0 ;
elsif rising_edge( CLOCK ) then
if ( iACNT = ACNT_MAX ) then
iACNT <= 0 ;
else
iACNT <= iACNT + 1 ;
end if ;
end if ;
end process ;
iACLK <= '1' when ( iACNT < ACNT_HALF ) else '0' ;
process ( nRESET , iACLK )
begin
if ( nRESET = '0' ) then
iBCNT <= 0 ;
elsif rising_edge( iACLK ) then
if ( iBCNT = BCNT_MAX ) then
iBCNT <= 0 ;
else
iBCNT <= iBCNT + 1 ;
end if ;
end if ;
end process ;
iBCLK <= '1' when ( iBCNT < BCNT_HALF ) else '0' ;
-- synchronizer
iLTRG <= '1' when ( iLSFT = "01" ) else '0' ;
iRTRG <= '1' when ( iRSFT = "01" ) else '0' ;
process( nRESET , iACLK )
begin
if ( nRESET = '0' ) then
iLSFT <= "00" ;
iRSFT <= "00" ;
elsif rising_edge( iACLK ) then
iLSFT <= iLSFT(0) & LSWT ;
iRSFT <= iRSFT(0) & RSWT ;
end if ;
end process;
-- sequencer
process( nRESET , iACLK )
begin
if ( nRESET = '0' ) then
iSTATE <= "00" ;
iWCNT <= 0 ;
elsif rising_edge( iACLK ) then
case conv_integer(iSTATE) is
-- wait trigger
when 0 => if ( iLTRG = '1' or iRTRG = '1' ) then
iSTATE <= "01" ;
else
iSTATE <= "00" ;
end if ;
-- enable and set counter
when 1 => iSTATE <= "11" ;
iWCNT <= LAST ;
-- wait and decrement
when 3 => if ( iWCNT = 0 ) then
iSTATE <= "10" ;
else
iSTATE <= "11" ;
iWCNT <= iWCNT - 1 ;
end if ;
-- disable and return first state
when 2 => iSTATE <= "00" ;
-- default
when others => iSTATE <= "00" ;
end case ;
end if ;
end process;
end Behavioral;
ピンアサインは、以下としました。
# system
NET "nRESET" loc = "P39" ;
NET "CLOCK" loc = "P5" ;
# monitor
NET "ACLK" loc = "P1" ;
NET "BCLK" loc = "P2" ;
# button
NET "RSWT" loc = "P8" ;
NET "LSWT" loc = "P9" ;
# right LED
NET "Rout<0>" loc = "P11" ;
NET "Rout<1>" loc = "P12" ;
NET "Rout<2>" loc = "P13" ;
NET "Rout<3>" loc = "P14" ;
# left LED
NET "Lout<0>" loc = "P18" ;
NET "Lout<1>" loc = "P19" ;
NET "Lout<2>" loc = "P20" ;
NET "Lout<3>" loc = "P22" ;
目次
前
次