[新連載]CPLD入門!
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
いつか使うことになるだろうと思ってはいたのですが。
何を今頃になって、というようなものですが。
ようやく本気で、CPLDと四つに取り組みます。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第109回]
●デジタル時計プログラム(3)
デジタル時計プログラムは[第104回]と[第105回]で紹介しました。
実は当初から気付いていたことなのですが、そこで紹介したプログラムにはちょっと使いづらいところがありました。
どういうことかといいますと。
時計の時刻表示を合わせるために、プッシュスイッチを使って時刻の初期設定を行ないます。
プッシュスイッチはA、B、Cの3個です。
このスイッチを使って桁ごとに設定を行なうために、スイッチAで時の2桁を、スイッチBで分の十の位の桁を、スイッチCで分の一の位の桁の設定を行ないます。
問題は秒です。
普通は秒まで設定しなくても、正秒(00秒)にあわせればよいので、秒の設定機能はありません(秒設定のためのスイッチが残っていない、という理由からでもあります)。
その代わりに、A、B、Cのいずれかのスイッチが押されているときには常に秒をゼロクリアするようにプログラムしました。
それでうまく考えたつもりだったのですが。
実際に時刻の設定を行なってみると、これが意外に使いにくいことがわかりました。
たとえば12時34分に設定したとします。
普通は12時34分の少し前にそのように設定しておいて、その時刻になったらスタートするようにします。
ところがこのプログラムには時計をストップさせておく機能がありません。
スイッチは全部時刻設定のために使っているのでストップのためのスイッチが残っていないからです。
設定のためにA、B、Cのいずれかを押している間は秒はゼロクリアされます。
スイッチから手を離すとすぐに秒のカウントが始まりますが、たとえば分の位をあわせるためにBとかCのスイッチを押せば、秒はまたゼロクリアされます。
しかし、そこに問題がありました。
12時34分に合わせてそこで手を離すと、すぐに秒カウントがスタートしてしまいます。
まだ12時34分になるにはもう少し待たなければなりません。
スタートしてしまった秒をクリアするには、A〜Cのどれかのスイッチを押せばよいのですが、するとせっかく設定した時刻がずれてしまいます。
それをあわせ直している間に12時34分になってしまうかもしれません。
ま。
サンプルプログラムですから。
本当のデジタル時計ではなくてトレーニングボードですし。
秒まで正確にあわせることはできません、ということで。
だってストップさせておくにはもうひとつそのためのスイッチが必要なんですから。
スイッチDを追加しておけばよかったのですけれど、レイアウトとしてはスイッチ3個がいっぱいのところでした。
なんとかできないかなあ、という思いはありました。
あと1個スイッチがあれば…。
あるじゃないの!
ありました。
スイッチじゃありませんが、ほら8ビットのジャンパピン入力が。
やっぱり考えてみるものです。
気が付いてみれば簡単なことでした。
ジャンパピンはSP1の右端の2ビットについては、7セグメントLEDに表示する時分、分秒などの切換えに使っていますが、その残りは未使用です。
そこでSP1の左端の1ビットにジャンパピンをセットしたときは秒はゼロクリアしてカウントしない、というようにプログラムを変更しました。
下は変更したプログラムを実行中の写真です。

12時34分に設定していますが、秒は00のままで停止しています。
右側の8個のLED(L18〜L25)にも秒がビット表示されます。
全ビットが消灯(=0)しています。
SP1の左端にジャンパピンをセットしています。
その部分を拡大しました。

下の写真では表示を分秒表示に切り換えています。

上の状態で、SP1の左端のジャンパピンを外すと、秒のカウントがスタートしました(下の写真)。

そのように変更したデジタル時計プログラムです。
--cpld training 19/5/25 5/26 5/27 5/28 5/29
--5/31 8/21 8/22 9/7
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library ARITHMETIC;
use ARITHMETIC.std_logic_arith.all;
entity trngwatch1d 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 trngwatch1d;
architecture rtl of trngwatch1d 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;
--
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;
--
-- ******* 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))
begin
if tm1(3)'event and tm1(3)='0' then
cntrss0<=cntrss0+"0001";
end if;
if cntrss0="1010" then
cntrss0<="0000";
end if;
end process;
--
--1/10sec
process(cntrss0(3))
begin
if cntrss0(3)'event and cntrss0(3)='0' then
cntrss1<=cntrss1+"001";
end if;
if cntrss1="1010" then
cntrss1<="0000";
end if;
end process;
--secondL
process(cntrss1(3),PCH(3))
begin
if cntrss1(3)'event and cntrss1(3)='0' then
cntrs0<=cntrs0+"0001";
end if;
if cntrs0="1010" or PCH(3)='0' then
cntrs0<="0000";
end if;
end process;
--secoudH
process(cntrs0(3),PCH(3))
begin
if cntrs0(3)'event and cntrs0(3)='0' then
cntrs1<=cntrs1+"001";
end if;
if cntrs1="110" or PCH(3)='0' then
cntrs1<="000";
end if;
end process;
--swcon set(every 1 second)
--select counterm0 clock
process(SWC,cntrs1(2),cntrss1(3))
begin
if SWC='0' then
cntrm0ck<=cntrss1(3);-- if SWC on,then count up every 1 sec
else
cntrm0ck<=cntrs1(2);
end if;
end process;
process(cntrm0ck)
begin
if cntrm0ck'event and cntrm0ck='0' then
cntrm0<=cntrm0+"0001";
end if;
if cntrm0="1010" then
cntrm0<="0000";
end if;
end process;
--minuteH
--swbon set(every 1 second)
--select counterm1 clock
process(SWB,cntrm0(3),cntrss1(3))
begin
if SWB='0' then
cntrm1ck<=cntrss1(3);-- if SWB on,then count up every 1 sec
else
cntrm1ck<=cntrm0(3);
end if;
end process;
--
process(cntrm1ck,SWC)
begin
if cntrm1ck'event and cntrm1ck='0' and SWC='1' then
cntrm1<=cntrm1+"001";
end if;
if cntrm1="110" then
cntrm1<="000";
end if;
end process;
--hour
--swaon set(every 1 second)
--select counterh clock
process(SWA,cntrm1(2),cntrss1(3))
begin
if SWA='0' then
cntrhck<=cntrss1(3);-- if SWA on,then count up every 1 sec
else
cntrhck<=cntrm1(2);
end if;
end process;
--
process(cntrhck,SWB)
begin
if cntrhck'event and cntrhck='0' and SWB='1' 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" 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;
|
変更したのは以下の部分だけです。
--secondL
process(cntrss1(3),PCH(3))
begin
if cntrss1(3)'event and cntrss1(3)='0' then
cntrs0<=cntrs0+"0001";
end if;
if cntrs0="1010" or PCH(3)='0' then
cntrs0<="0000";
end if;
end process;
--secoudH
process(cntrs0(3),PCH(3))
begin
if cntrs0(3)'event and cntrs0(3)='0' then
cntrs1<=cntrs1+"001";
end if;
if cntrs1="110" or PCH(3)='0' then
cntrs1<="000";
end if;
end process;
|
cntrs0とcntrs1がクリアされるところにPCH(3)=’0’を追加しました。
PCH(3)はSP1の左端の入力です。
下は今回変更したプログラムのソースファイルです。
trngwatch1d.txt
[第91回]の通りに作業してください。
今回新規作成するフォルダはtrngwatch1dです。
作業が済んだら[第92回]以後のところを参考にしてコンパイル等の作業を行なってください。
CPLD入門![第109回]
2019.9.9upload
前へ
次へ
ホームページトップへ戻る