[新連載]CPLD入門!
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
いつか使うことになるだろうと思ってはいたのですが。
何を今頃になって、というようなものですが。
ようやく本気で、CPLDと四つに取り組みます。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第110回]
●ストップウォッチプログラム
ストップウォッチプログラムはデジタル時計プログラムの応用です。
応用というより流用というほうが適切かもしれません。
デジタル時計プログラムの時刻設定部分を削除して、代わりにスタート/ストップと全部の桁のクリア機能を追加しました。
7セグメントLEDへの時分、分秒、秒1/100秒表示の切換え機能はデジタル時計プログラムと同じです。
ゼロクリアしてスタートしたあと、適当なところでストップしました。
ゼロクリアはスイッチA(S1)を押します。
スタート/ストップはスイッチC(S3)を押します。
ゼロクリアするとストップ(スタンバイ)状態で、スタートスイッチ(スイッチC、S3)が押されるのを待ちます。
スタートスイッチが押されると、現在のカウンタの状態からカウントを開始します。
もう一度スタートスイッチ(スイッチC、S3)を押すとそこでカウントを停止して、次にゼロクリアスイッチ(スイッチA、S1)が押されるかもう一度スタートスイッチ(スイッチC、S3)が押されるまでそのままスタンバイします。
上の写真ではSP1の右端のビットにジャンパピンをセットしています。
このとき7セグメントLEDには秒2桁と1/100秒2桁が表示されます。
もう一度スタートスイッチ(スイッチC、S3)を押して、カウントが再開されました。
ゼロクリアスイッチ(スイッチA、S1)を押して、全桁をクリアしました。
下はストップウオッチプログラムのソースプログラムリストです。
--cpld training 19/5/25 5/26 5/27 5/28 5/29 --5/31 8/21 8/22 9/7 9/8 9/9 library IEEE; use IEEE.STD_LOGIC_1164.ALL; library ARITHMETIC; use ARITHMETIC.std_logic_arith.all; entity trngspwatch1a is PORT ( -- T27:out std_logic; -- T29:out std_logic; SEGOUT:out std_logic_vector(7 downto 0); LEDOUT:out std_logic_vector(3 downto 0); CK1:in std_logic; -- CK2:in std_logic; -- CK3:in std_logic; SWA:in std_logic; -- SWB:in std_logic; SWC:in std_logic; -- ADRSIN:in std_logic_vector(7 downto 0); -- DINOUT:inout std_logic_vector(7 downto 0); PA:out std_logic_vector(7 downto 0); PB:out std_logic_vector(7 downto 0); PCL:in std_logic_vector(3 downto 0); PCH:in std_logic_vector(3 downto 0) ); -- IOR:in std_logic; -- IOW:in std_logic); end trngspwatch1a; architecture rtl of trngspwatch1a is signal cntr1:std_logic_vector(11 downto 0);--1khz 4096=2**12 signal tm1:std_logic_vector(3 downto 0);--1/1000 sec signal cntrss0:std_logic_vector(3 downto 0);--1/100 sec signal cntrss1:std_logic_vector(3 downto 0);--1/10 sec signal leddatabf0:std_logic_vector(3 downto 0); signal leddatabf1:std_logic_vector(3 downto 0); signal leddatabf2:std_logic_vector(3 downto 0); signal leddatabf3:std_logic_vector(3 downto 0); signal leddatawk:std_logic_vector(3 downto 0); signal segdata:std_logic_vector(7 downto 0); signal ledoutbf:std_logic_vector(3 downto 0); signal ledcntr:std_logic_vector(2 downto 0); signal ledadrs:std_logic_vector(2 downto 0); signal cntrs0:std_logic_vector(3 downto 0); signal cntrs1:std_logic_vector(2 downto 0); signal cntrm0:std_logic_vector(3 downto 0); signal cntrm1:std_logic_vector(2 downto 0); signal cntrh:std_logic_vector(5 downto 0); --signal cntrh1:std_logic_vector(1 downto 0); signal tm0:std_logic; signal cntrm0ck:std_logic; signal cntrm1ck:std_logic; signal cntrhck:std_logic; signal stopgo:std_logic; -- begin PA<=cntrss1 & cntrss0; PB<='0' & cntrs1 & cntrs0; -- 7seg drive clock 1KHz from 4096KHz process(CK1) begin if CK1'event and CK1='1' then cntr1<=cntr1+"000000000001"; end if; end process; -- led drive,LEDOUT process(cntr1) begin if cntr1(11)'event and cntr1(11)='0' then ledcntr<=ledcntr+"001"; ledoutbf<=ledoutbf(2 downto 0) & '0'; end if; if ledcntr(2)='1' then ledcntr<="000"; ledoutbf<="0001"; end if; end process; -- LEDOUT<=ledoutbf; SEGOUT<=segdata; -- led data out process(ledcntr) begin if ledcntr(1 downto 0)="00" then leddatawk<=leddatabf0; elsif ledcntr(1 downto 0)="01" then leddatawk<=leddatabf1; elsif ledcntr(1 downto 0)="10" then leddatawk<=leddatabf2; elsif ledcntr(1 downto 0)="11" then leddatawk<=leddatabf3; end if; end process; --segment change process(leddatawk) begin if leddatawk="0000" then segdata<="01011100"; elsif leddatawk="0001" then segdata<="00000110"; elsif leddatawk="0010" then segdata<="01011011"; elsif leddatawk="0011" then segdata<="01001111"; elsif leddatawk="0100" then segdata<="01100110"; elsif leddatawk="0101" then segdata<="01101101"; elsif leddatawk="0110" then segdata<="01111101"; elsif leddatawk="0111" then segdata<="00000111"; elsif leddatawk="1000" then segdata<="01111111"; elsif leddatawk="1001" then segdata<="01101111"; end if; end process; --stop and go process(SWC) begin if SWC'event and SWC='0' then stopgo<=stopgo+'1'; end if; if SWA='0' then stopgo<='0'; end if; end process; -- -- ******* watch ****** -- tm0<=cntr1(11); --1/1000 process(tm0) begin if tm0'event and tm0='0' then tm1<=tm1+"0001"; end if; if tm1="1010" then tm1<="0000"; end if; end process; -- 1/100sec process(tm1(3),SWA) begin if tm1(3)'event and tm1(3)='0' and stopgo='1' then cntrss0<=cntrss0+"0001"; end if; if cntrss0="1010" or SWA='0' then cntrss0<="0000"; end if; end process; -- --1/10sec process(cntrss0(3),SWA) begin if cntrss0(3)'event and cntrss0(3)='0' then cntrss1<=cntrss1+"001"; end if; if cntrss1="1010" or SWA='0' then cntrss1<="0000"; end if; end process; --secondL process(cntrss1(3),SWA) begin if cntrss1(3)'event and cntrss1(3)='0' then cntrs0<=cntrs0+"0001"; end if; if cntrs0="1010" or SWA='0' then cntrs0<="0000"; end if; end process; --secoudH process(cntrs0(3),SWA) begin if cntrs0(3)'event and cntrs0(3)='0' then cntrs1<=cntrs1+"001"; end if; if cntrs1="110" or SWA='0' then cntrs1<="000"; end if; end process; cntrm0ck<=cntrs1(2); process(cntrm0ck,SWA) begin if cntrm0ck'event and cntrm0ck='0' then cntrm0<=cntrm0+"0001"; end if; if cntrm0="1010" or SWA='0' then cntrm0<="0000"; end if; end process; --minuteH cntrm1ck<=cntrm0(3); -- process(cntrm1ck,SWA) begin if cntrm1ck'event and cntrm1ck='0' then cntrm1<=cntrm1+"001"; end if; if cntrm1="110" or SWA='0' then cntrm1<="000"; end if; end process; --hour cntrhck<=cntrm1(2); -- process(cntrhck,SWA) begin if cntrhck'event and cntrhck='0' then cntrh<=cntrh+"000001"; end if; if cntrh(3 downto 0)="1010" then cntrh(3 downto 0)<="0000"; cntrh(5 downto 4)<=cntrh(5 downto 4)+"01"; elsif cntrh="100100" or SWA='0' then cntrh<="000000"; end if; end process; --7seg disp select --HHMM or MMSS process(PCL,cntrss0,cntrss1,cntrs0,cntrs1,cntrm0,cntrm1) begin if PCL(0)='0' then leddatabf3<=cntrss0; leddatabf2<=cntrss1; leddatabf1<=cntrs0; leddatabf0<='0' & cntrs1; elsif PCL(1)='0' then leddatabf3<=cntrs0; leddatabf2<='0' & cntrs1; leddatabf1<=cntrm0; leddatabf0<='0' & cntrm1; else leddatabf3<=cntrm0; leddatabf2<='0' & cntrm1; leddatabf1<=cntrh(3 downto 0); leddatabf0<="00" & cntrh(5 downto 4); end if; end process; -- end rtl; |
-- ******* watch ******以下の各桁のクリア部分にSWA=’0’を書き加えました。
デジタル時計プログラムで時刻設定のために、SWA〜SWCの入力によってクロックのソースを切り換えていたところと、下の桁を設定するためのカウントアップの繰り上がりが上の桁に影響しないようにしている部分を外しました。
プログラムはそれだけ簡単になっています。
スイッチCによってスタート/ストップするところは以下の部分です。
--stop and go process(SWC) begin if SWC'event and SWC='0' then stopgo<=stopgo+'1'; end if; if SWA='0' then stopgo<='0'; end if; end process; -- |
ここでスイッチCを押すたびにstopgo変数に’1’と’0’を交互に入れ替えています。
stopgo=’1’のときに1/100秒のところでカウンタがカウントを開始します。
下は上のプログラムのソースファイルです。
trngspwatch1a.txt
[第91回]の通りに作業してください。
今回新規作成するフォルダはtrngspwatch1aです。
作業が済んだら[第92回]以後のところを参考にしてコンパイル等の作業を行なってください。
●既知の問題
1)前回のデジタル時計プログラムで電源ONのときに分の表示がゾロ目(33とか55とか)になることがあります。
このときに時刻設定のためにスイッチBを押すと、本来は分の上位桁(十分の桁)のみがアップされるはずなのですが、下位の一の桁も同時に動いてしまいます。
一度スイッチCを押すとこの現象は止まります。
以後は正常に動くようになります。
電源ONのときに不安定な状態で起動してしまうのではないかと思っていますが、原因はよくわかりません。
2)何も書き込まれていないEPM7128SLC84にProgrammerで初めて書き込みを行なったときなどに発生することが多いようですが、100%書き込みが完了した直後に書き込みエラーの表示が出ることがあります。
しかし見たところ書き込みを行なったEPM7128SLC84は正常にプログラム動作をしているようです。
念のためUSB Blasterケーブルを外し、Programmerを終了して、EPM7128SLC84の電源も切ったあと、再び電源をONにして、USB Blasterケーブルを接続してProgrammerを起動して再度書き込みを行なうと、今度は正常に書き込みが完了します(100%success)。
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
当連載を開始してからもう半年以上経ってしまいました。
やっとなんとか一区切りつくところまでたどりつきました。
CPLDを使ったボードについては、今までに紹介したボード以外にも色々考えているものがあって、その中には試作の段階まで進んでいるものもあります。
しかしCPLD以外にも作りたいものがまだまだ沢山あるので、ずっとCPLDのみの連載を続けるというわけにはいきません。
この辺でしばらくCPLDの連載からは離れることにしまして、別の連載に取り掛かりたいと思います。
CPLD関連のボードについては、具体化した段階でその都度この連載の続きとして紹介することにいたします。
CPLD入門![第110回]
2019.9.10upload
前へ
次へ
ホームページトップへ戻る