目次
前
次
定番回路確認
マイコンを利用した動作確認は、LEDチカチカ
(Lチカと省略されてることが多い)ですが
自分の中の定番回路は、蛍のエミュレートです。
2個のLEDを使い、1個のLEDはジワリと点灯し
他の1個は消灯ということを、交互に繰返し。
ブレッドボード上の回路は、以下。
発振回路を応用して、次のVHDLコードで実現。
-- hotal
iHOTAL(0) <= '1' when ( iCNT < iREG ) else '0' ;
iHOTAL(1) <= not iHOTAL(0) ;
-- PWM
process ( nRESET , iACLK )
begin
if ( nRESET = '0' ) then
iCNT <= 0 ;
elsif rising_edge( iACLK ) then
if ( iCNT = LAST ) then
iCNT <= 0 ;
else
iCNT <= iCNT + 1 ;
end if ;
end if ;
end process ;
-- register
process ( nRESET , iBCLK )
begin
if ( nRESET = '0' ) then
iREG <= 19 ;
elsif rising_edge( iBCLK ) then
if ( iREG >= LAST ) then
iREG <= 19 ;
else
iREG <= iREG + 3 ;
end if ;
end if ;
end process ;
2個のLEDを使うので、位相を180度変えて波形を出力。
ジワリと点灯するのは、PWM波形をLEDに転送。
PWM波形は、カウンタと参照レジスタを利用すれば
簡単に生成できるので、process文を使って記述。
カウンタは、0から99までを1kHzで生成。
レジスタは、19から99までを1Hzで生成。
レジスタは、増分を3にして変化の度合いを調整してます。
システムクロックを4MHzとして、分周器を入れて
1kHzと1Hzを生成します。ブロック図は、以下。
ブロック図が描けば、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' ;
カウンタとレジスタのクロックでは、DUTY比が
50%になるように指定。
定数は、CONSTANTを利用して定義。
CONSTANT ACNT_MAX : integer := 3999 ;
CONSTANT BCNT_MAX : integer := 999 ;
CONSTANT ACNT_HALF : integer := 2000 ;
CONSTANT BCNT_HALF : integer := 500 ;
CONSTANT LAST : integer := 99 ;
また、レジスタはintegerを利用してわかりやすく
かつ範囲を限定してバグが入らないようにします。
signal iACNT : integer range 0 to ACNT_MAX ;
signal iBCNT : integer range 0 to BCNT_MAX ;
rangeを利用すると、std_logic_vectorを
使わずに、ビット幅を調整できます。
ビット幅の計算は、2進数での範囲指定と
なるので、面倒なことは処理系に一任して
と考えて、余計なことに頭を使わないよう
にします。
まとめると、以下。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity chotal is
Port (
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ; -- 4MHz
-- clock monitor
ACLK : out std_logic ;
BCLK : out std_logic ;
-- output
HOTAL : out std_logic_vector(1 downto 0) --;
);
end chotal;
architecture Behavioral of chotal is
--
CONSTANT ACNT_MAX : integer := 3999 ;
CONSTANT BCNT_MAX : integer := 999 ;
CONSTANT ACNT_HALF : integer := 2000 ;
CONSTANT BCNT_HALF : integer := 500 ;
CONSTANT LAST : integer := 99 ;
-- 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 ;
-- PWM
signal iCNT : integer range 0 to LAST ;
-- register
signal iREG : integer range 0 to LAST ;
-- hotal
signal iHOTAL : std_logic_vector(1 downto 0) ;
begin
-- output
HOTAL <= iHOTAL ;
ACLK <= iACLK ;
BCLK <= iBCLK ;
-- hotal
iHOTAL(0) <= '1' when ( iCNT < iREG ) else '0' ;
iHOTAL(1) <= not iHOTAL(0) ;
-- 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' ;
-- PWM
process ( nRESET , iACLK )
begin
if ( nRESET = '0' ) then
iCNT <= 0 ;
elsif rising_edge( iACLK ) then
if ( iCNT = LAST ) then
iCNT <= 0 ;
else
iCNT <= iCNT + 1 ;
end if ;
end if ;
end process ;
-- register
process ( nRESET , iBCLK )
begin
if ( nRESET = '0' ) then
iREG <= 19 ;
elsif rising_edge( iBCLK ) then
if ( iREG >= LAST ) then
iREG <= 19 ;
else
iREG <= iREG + 3 ;
end if ;
end if ;
end process ;
end Behavioral;
2種のクロックを生成していることが
わかるよう、モニタピンを使ってます。
ピンアサインは、以下。
# system
NET "nRESET" loc = "P39" ;
NET "CLOCK" loc = "P5" ;
# monitor
NET "ACLK" loc = "P1" ;
NET "BCLK" loc = "P2" ;
# hotal
NET "CHOTAL<0>" loc = "P8" ;
NET "CHOTAL<1>" loc = "P9" ;
LEDの点滅は、次の基板に接続して確認しました。
目次
前
次