アフィリエイト広告
アフィリエイト広告

74HC161A / 時表示用 12進カウンタをつくる

4bit 同期バイナリカウンタ 74HC161A を使って 60進カウンタができました。これで、秒と分のカウントができますから、やっぱり次は、時をカウントする 12進カウンタをつくらないといけない、のです。

フリップフロップを使ったカウンタについては、こちらもあわせてご覧ください。

時表示用 12進カウンタ回路

時表示用のカウンタは、単純に 12 数えるだけではダメです。時刻は 12時から始まって、12時に終わるのですから。しかも、午前と午後がある。考えるほどに、だんだん、頭が、痛くなる (;´Д`)

回路図

図1 が、時刻用 12進カウンタの回路図です。時刻表示は、以前と同様に 12時間計とし、午後信号 (12時~11時) を出力します。まぁ Q を取り出せば午前信号にもなるんですけどね。

図1. 12進カウンタ 回路図

左は 4bit 同期カウンタIC 74HC161A。1の位の BCD データ 4bit を出力します。

中央上が Dフリップフロップ 74HC74A で、10の位を出力します。10位は 0 か 1 だけなので、非同期のトグル動作にしています。

右上も Dフリップフロップ 74HC74A で、午後の信号を出力します。これも表示切り換えだけなので、非同期のトグル動作にしています。

組み合わせ回路を構成する

IC1 (4bit 同期カウンタ 74HC161A) と、組み合わせ回路 IC2 (NANDゲート 74HC00) は、1の位のカウンタを構成します。
時表示は、1、2 … 9、10、11、12、1、2 … と遷移します。そこで、1の位の出力が 0x9 のときに 0x0 をロードし、その他のときは 0x1 をロードすることにします。プリセットデータの LSB は入力 A ですので、

A = QD⋅QA

B、C、D は 0 に固定、つまり GND に接続しておきます。

ロードさせるタイミングは、カウントイネーブルで、出力が 0x09 のときと 0x12 のときです。したがって LD は、

LD = (QD⋅QA + QE⋅QB)⋅CE

となります。ここで QE は 10の位の出力、CE は下位カウンタからのキャリー (カウントイネーブル) 信号です。

10の位の切り換えは、出力が 0x09 と 0x12 で行ないます。切り換え信号を CA とすると、

CA = QD⋅QA + QE⋅QB

これを U1/IC4 (Dフリップフロップ 74HC74A) のクロックとして入力し、トグル動作させています。カウンタ回路と考えるなら同期させるべきかもしれませんが、ここは簡単にすませることにしました。
ちなみに、信号を反転させているのは、次のクロックで動作させるためです。

午前/午後切り換え信号は、出力が 0x12 になったときにトグルするようにします。午前/午後切り換え信号を SA とすると、

SA = QE⋅QB

こちらは U2/IC4 (Dフリップフロップ 74HC74A) のクロックとして入力します。上にも書きましたが、出力 Q は午後を、Q は午前を表示する信号になります。回路図には午後信号しか取り出していないです。

以上の論理式にしたがって回路図を作成していますが、すべてを NAND ゲートにするために、論理式を少し変形してます。さほど難しい変形ではないので、比較してみればすぐにわかると思います。

VerilogHDL によるシミュレーション

VerilogHDL で動作を確認してみます。

IC をモジュールにする

使っている IC をモジュールにしておくと便利かなと思うので、4bit 同期カウンタ 74HC161A と Dフリップフロップ 74HC74A をそれぞれ記述しておくことにします。

74HC161A はこれまでも使ってきた回路記述です。変更はありません。

74HC161A 回路記述
  1. module TC74HC161A (
  2.   input wire CK, CLR, LD, ENT, ENP,
  3.   input wire [3:0] PRE,
  4.   output reg [3:0] Q,
  5.   output wire CO
  6. );
  7.   always @(posedge CK, negedge CLR) begin
  8.     if(1'b0 == CLR) begin
  9.       Q <= 4'h0;
  10.     end
  11.     else if(1'b0 == LD) begin
  12.       Q <= PRE;
  13.     end
  14.     else if(1'b0 == ENT || 1'b0 == ENP) begin
  15.     end
  16.     else begin
  17.       Q <= Q + 4'h1;
  18.     end
  19.   end
  20.   assign CO = (1'b1 == ENT && 4'hf == Q);
  21. endmodule

74HC74A を新たに記述しました。
プリセット PR とクリア CLR の動きでちょっと未確認なところがあるのですが、まぁ通常の動作に影響はないと思います。そのうち、気が向いたら確認します。

74HC74A 回路記述
  1. module TC74HC74A (
  2.   input wire D, CK, PR, CLR,
  3.   output reg Q, NQ
  4. );
  5.   always @(posedge CK, negedge PR, negedge CLR) begin
  6.     if(1'b0 == CLR) begin
  7.       if(1'b0 == PR) begin
  8.         Q <= 1'b1;
  9.         NQ <= 1'b1;
  10.       end
  11.       else begin
  12.         Q <= 1'b0;
  13.         NQ <= 1'b1;
  14.       end
  15.     end
  16.     else if(1'b0 == PR) begin
  17.       Q <= 1'b1;
  18.       NQ <= 1'b0;
  19.     end
  20.     else begin
  21.       Q <= D;
  22.       NQ <= ~D;
  23.     end
  24.   end
  25. endmodule

12進カウンタの動作シミュレーション

12進カウンタの回路を記述します。
10行目の PRE はプリセットデータですが、A だけでなく 4bit で扱って、セレクタで切り換えています。あとは上の論理式にしたがって記述し、下位モジュールとして IC を接続しています。

12進カウンタ 回路記述
  1. module COUNTER_MOD12 (
  2.   input wire CK, RESET, CE,
  3.   output wire [3:0] Q0,
  4.   output wire Q1, PM
  5. );
  6.   wire [3:0] PRE;
  7.   wire LD, CA, SA;
  8.   assign PRE = (Q0[3] & Q0[0]) ? 4'h0 : 4'h1;
  9.   assign LD = ~((Q0[3] & Q0[0] | Q1 & Q0[1]) & CE);
  10.   assign CA = ~(Q0[3] & Q0[0] | Q1 & Q0[1]);
  11.   assign SA = Q1 & Q0[1];
  12.   TC74HC161A U0(CK, RESET, LD, CE, 1'b1, PRE, Q0, CO);
  13.   TC74HC74A U1(NQ1, CA, 1'b1, RESET, Q1, NQ1);
  14.   TC74HC74A U2(NQ2, SA, 1'b1, RESET, PM, NQ2);
  15. endmodule

図2 が、シミュレーションの結果です。
じっさいの回路では、3600 クロックごとに CE が HIGH になり、そのときにカウントアップするように動作します。が、ここでは、クロックをカウントして、出力の遷移が想定通りになるかどうかを確認しています。

図2. 12進カウンタ シミュレーション結果

Q0 は 1の位の 4bit BCD 出力。Q1 は、HIGH のとき 10の位を 1 としています。なお、電源オン時などリセットしたときは 0 からスタートし、1 へ遷移します。12 に初期化させるには、そのための回路が必要になるので、やめました。どうせ時刻合わせしないといけないし、いいでしょ。
午後信号は、12〜11 で出力します。午前 0時は「午前12時」、正午は「午後12時」となります。

後記

今回は、デジタル時計の時表示用の 12進カウンタをつくりました。

1 から始まって 12 で終わる、時表示って悩ましいですよねぇ。
以前フリップフロップでやったときは、5bit カウンタ BCD 出力で設計しました。単純に 0x1〜0xC を出力して、9セグメントへデコードするって手もあります。あっさり 24時間計にしちゃえば簡単かもしれない。
今回の回路も、10の位にも 74HC161A 使ったほうがきれいだったかもしれません。

ま、いろんな方法があると思いますが、基本、部品箱にあるものを使おうってのは、いつも同じです。

さてと、カウンタ部分ができましたので、これ、デジタル時計にしましょう。次回から、周辺の回路をつくっていきます。

タイトルとURLをコピーしました