アフィリエイト広告

論理回路 / シフトレジスタ・ジョンソンカウンタ・リングカウンタ

デジタル時計をつくったりして時間があいてしまいましたが、論理回路の勉強を続けましょう。
今回は、シフトレジスタと、それを応用したカウンタを試してみます。

シフトレジスタ

シフトレジスタとは、複数のフリップフロップがカスケード接続された構造で、クロックパルスが入力されるたびに、記憶されているデータが次のフリップフロップへ移動していく論理回路です。
詳しくは、ググってください m(_ _;)m

フリップフロップの伝送遅延時間

図1. フリップフロップの伝送遅延時間

シフトレジスタの動作を理解するうえでのポイントは、クロックが入ってからフリップフロップの出力が変化するのに、伝送遅延時間があるってこと。

図1 は、実験に使った Dフリップフロップ 74HC74A の、クロック (黄) と出力 (青) の立ち上がり部の波形です。クロックが入って、10nsほど遅れて出力がでていることがわかります。

クロックより遅れて出力が立ち上がるから、次段のフリップフロップの出力は次のクロックの立ち上がりで動作する。そうしてフリップフロップは、クロックひとつづつ遅れて順番に動いていき、データが移動していくようになる。ということ。

ちなみに、74HC74A のデータシートでは、伝送遅延時間は 16ns (Vcc=4.5V、標準) になっていました。最小値の規定がないのですが、まぁだいたいこのぐらいってことなのだろうと思います。

周辺回路

まず、実験に必要な周辺の回路をつくっておきましょう。

図2. クロック発振回路

図2 は、クロック発振回路です。
なんでもいいんですけど、前回の記事でつくったオペアンプを使った矩形波発振回路がありましたので、それを使っています。
どうせ 74HC14 使うので、こっちとかが簡単でおすすめです。

発振周波数は約 2Hz。ボリューム RV1 は、出力パルスのデューティ比の調整用で、デューティ比 50%に調整しておきます。

図3. 初期化回路

図3。毎度毎度の、電源オン時にフリップフロップを初期化する回路です。

フリップフロップは、電源オン時に出力が不定になりますので、CLR を LOW にして、出力を初期化しておきます。
電源オン後 500msで HIGH が出力されます。

R7 は ICの保護抵抗です。

図4. LED 表示回路

図4 は、フリップフロップの各段の出力を LED 表示するための回路です。
LED の表示によって、シフトレジスタの動きがわかると思います。

LED電流は約 0.6mA。ふつうの高輝度 LEDなら、この程度の電流でもじゅうぶんに光ります。

図5. 押しボタン回路

図5 は、入力信号を与えるための押しボタン回路です。

R13、C3のフィルタ回路でチャタリングを抑止し、シュミットトリガで波形整形します。
R12 はプルアップ、R14は保護抵抗です。

シフトレジスタの回路

シフトレジスタには、入力がシリアルのものとパラレルのものがあります。また、出力もシリアル、パラレル両方があります。今回はそのうち、シリアル入力パラレル出力 (Serial-In, Parallel-Out, SIPO) で、フリップフロップが 4段の 4ビットシフトレジスタをつくってみました。
74HCシリーズだと 74HC164 が相当しますが、74HC164 はフリップフロップが 8つ接続されている 8ビットシフトレジスタですので、その半分の規模です。

図6. 4ビット SIPO シフトレジスタ回路図

使ったのは、Dフリップフロップの 74HC74A です。ググるとよくでてくる回路ですね。
出力 Q0~Q3 の初期値は 0 です。押しボタンを押下して SER が 1 になると、最初のクロックの立ち上がりで Q0 が 1、次のクロックで Q1 が 1 になり、クロックが入るたびに次段に送られていきます。SER が 0 になると、それも順番に次段に移動していきます。

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

オシロスコープでは全体の信号の動きが見られないので、verilogHDL でシミュレーションしてみました。

verilogHDL シフトレジスタ回路記述
  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 // TC74HC74A
  26. module ShiftRegister (
  27.   input wire CLK, CLR, SER,
  28.   output wire [3:0] Q,
  29.   output wire [3:0] NQ
  30. );
  31.   TC74HC74A ff0(.D(SER), .CK(CLK), .PR(1'b1), .CLR(CLR), .Q(Q[0]), .NQ(NQ[0]));
  32.   TC74HC74A ff1(.D(Q[0]), .CK(CLK), .PR(1'b1), .CLR(CLR), .Q(Q[1]), .NQ(NQ[1]));
  33.   TC74HC74A ff2(.D(Q[1]), .CK(CLK), .PR(1'b1), .CLR(CLR), .Q(Q[2]), .NQ(NQ[2]));
  34.   TC74HC74A ff3(.D(Q[2]), .CK(CLK), .PR(1'b1), .CLR(CLR), .Q(Q[3]), .NQ(NQ[3]));
  35. endmodule // ShiftRegister

回路記述は、一般的なシフトレジスタの記述ではなく、図6 の回路をそのまま記述しています。1~27行目が、使用した 74HC74A のモジュール。これを下位モジュールとして接続 (35~38行目) し、シフトレジスタ回路をつくっています。

シミュレーションの結果が、図7 です。

図7. シフトレジスタのシミュレーション波形

入力 SER が入ると、その信号が Q[0]~Q[3] へとシフトしていくようすがわかります。そして、Q[3] を通り過ぎた信号は、どこかへと消え去ってしまうのです (^_^;)
同じシフトレジスタでも、74HC595 は出力にストレージレジスタを持っていますので、各出力値を保持できるんですけどね。74HC164 では、データはどんどんシフトしていってしまいます。

ジョンソンカウンタ

シフトレジスタができましたので、それを応用したカウンタをつくってみましょう。まずはジョンソンカウンタと呼ばれる回路です。

ジョンソンカウンタ回路図

ジョンソンカウンタとは、ジョンソンさんがつくったカウンタです (^_^;)

図8. ジョンソンカウンタ回路図

シフトレジスタと、どこが違う?
初段の信号入力が Q3 になっています。Q3 とは、最終段の出力を反転させた信号。ジョンソンカウンタとは、最終段の出力を反転させて初段の入力にもどし、ループにした回路です。

ジョンソンカウンタのシミュレーション (非対称型)

シミュレーションしてみましょう。

verilogHDL ジョンソンカウンタ回路記述
  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 // 74HC74A
  26. module JohnsonCounter (
  27.   input wire CLK, CLR,
  28.   output wire [3:0] Q,
  29.   output wire [3:0] NQ
  30. );
  31.   TC74HC74A ff0(.D(NQ[3]), .CK(CLK), .PR(1'b1), .CLR(CLR), .Q(Q[0]), .NQ(NQ[0]));
  32.   TC74HC74A ff1(.D(Q[0]), .CK(CLK), .PR(1'b1), .CLR(CLR), .Q(Q[1]), .NQ(NQ[1]));
  33.   TC74HC74A ff2(.D(Q[1]), .CK(CLK), .PR(1'b1), .CLR(CLR), .Q(Q[2]), .NQ(NQ[2]));
  34.   TC74HC74A ff3(.D(Q[2]), .CK(CLK), .PR(1'b1), .CLR(CLR), .Q(Q[3]), .NQ(NQ[3]));
  35. endmodule // JohnsonCounter

シフトレジスタと同様に、図8 の回路をそのまま記述しています。初段のインスタンス ff0 の入力は、最終段 ff3 の反転出力になっています。

図9. ジョンソンカウンタのシミュレーション波形 (非対称型)

Q[3..0]Q3Q2Q1Q0
0x00000
0x10001
0x30011
0x70111
0xF1111
0xE1110
0xC1100
0x81000
表1. 非対称型ジョンソンカウンタ コード表

初期化後の Q3 は 1 です。それが初段の入力になるので、各出力は順次 1 になっていきます。最終段の出力 Q3 が 1 になると、Q3 は 0。それが初段にもどるので、今度は順次 0 になっていきます。最終段が 0 になると入力はまた 1 になる。それを繰り返します。

これは 8分周回路になっていることがわかります。ジョンソンカウンタは、段数 x2 の分周回路です。たとえば 3段目の出力をもどせば、6分周回路になります。8ビットの 74HC164 を利用すれば、最大 16分周することが可能です。

表1 は、ジョンソンカウンタの出力をビットコードにしたものです。

1 の数が増えていって、全部が 1 (0xF) になると、今度は減っていきます。このように、0 と 1 の期間が不均一のものを「非対称型」と呼びます。

ジョンソンカウンタのシミュレーション (対称型)

では、初段にもどす信号を 2段目の Q1 にするとどうなるでしょう。シミュレーションしてみます。

verilogHDL ジョンソンカウンタ回路記述 変更箇所
  1.   TC74HC74A ff0(.D(NQ[1]), .CK(CLK), .PR(1'b1), .CLR(CLR), .Q(Q[0]), .NQ(NQ[0]));
図10. ジョンソンカウンタのシミュレーション波形 (対称型)

Q[3..0]Q3Q2Q1Q0
0x30011
0x60110
0xC1100
0x91001
表2. 対称型ジョンソンカウンタ コード表

2段目の出力をもどしているので 4分周回路になりましたが、フリップフロップは 4段あるので、出力は 4ビットのままです。

表2 が、出力コードです。
すべての状態で、1 と 0 の数が同じになりました。これを「対称型」と呼びます。

ということは、Q3 をもどす非対称型でも、フリップフロップを 8段にすれば対称型になる。容易に想像できますね。

リングカウンタ

ジョンソンカウンタもリングカウンタの一種なのですが、最終段の出力を反転せずに、そのまま初段にもどすのがリングカウンタです。
ただ、初期化時にはすべての出力が 0 なので、最初だけ 1 を与えてやらないといけません。初期化時に初段を 1 にセットするという方法もありますが、ふつうは「最終段を除く出力がすべて 0 になったときに 1 をもどす」という方法をとります。

リングカウンタ回路図

図11 が、「最終段を除く出力がすべて 0 のとき 1 をもどす」リングカウンタの回路です。

図11. リングカウンタ回路図

「すべての出力 (Q0, Q1, Q2) が 0 のとき 1 を出力 (D) する」を論理式にすると、

D = Q0Q1Q2

なので、フリップフロップの反転出力を AND すればよいとわかります。

ジョンソンカウンタと同様に、基本はシフトレジスタと同じです。AND ゲート 74HC08 を追加しました。

リングカウンタのシミュレーション

verilogHDL でシミュレーションしてみましょう。

verlogHDL リングカウンタ回路記述
  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 // 74HC74A
  26. module RingCounter (
  27.   input wire CLK, CLR,
  28.   output wire [3:0] Q,
  29.   output wire [3:0] NQ
  30. );
  31.   wire D;
  32.   assign D = NQ[0] & NQ[1] & NQ[2];
  33.   TC74HC74A ff0(.D(D), .CK(CLK), .PR(1'b1), .CLR(CLR), .Q(Q[0]), .NQ(NQ[0]));
  34.   TC74HC74A ff1(.D(Q[0]), .CK(CLK), .PR(1'b1), .CLR(CLR), .Q(Q[1]), .NQ(NQ[1]));
  35.   TC74HC74A ff2(.D(Q[1]), .CK(CLK), .PR(1'b1), .CLR(CLR), .Q(Q[2]), .NQ(NQ[2]));
  36.   TC74HC74A ff3(.D(Q[2]), .CK(CLK), .PR(1'b1), .CLR(CLR), .Q(Q[3]), .NQ(NQ[3]));
  37. endmodule // RingCounter

37行目に ANDゲートを追加しています。

図12. リングカウンタ シミュレーション波形

Q[3..0]Q3Q2Q1Q0
0x10001
0x20010
0x40100
0x81000
表3. リングカウンタ コード表

出力波形は、最初に入力した 1 が順番にシフトして、最終段から初段へ循環していることがわかります。

表3 が、出力コード表です。

リングカウンタの出力は、1 が常に 1ビットだけで、バイナリコードをデコードしたような信号になります。
また、リングカウンタは段数の分周回路になります。図11 は 4段なので 4分周回路です。

ブレッドボード

図13. 実験中のブレッドボード

リングカウンタを実験中のブレッドボードです。

上は 5V電源回路。真ん中が、オペアンプを使ったクロック発振回路です。

下のブレッドボードは、左に押しボタンスイッチ回路と初期化回路の 74HC14。中央の 2個の ICが 74HC74 のシフトレジスタ。右が 74HC08。一番左は LEDの表示回路です。

まいどなんですが、シミュレーションだけじゃなくて、じっさいに回路を組んで試してみたよ、って話です (;´Д`)

後記

今回は、シフトレジスタと、それを使ったカウンタを勉強しました。
あとは、パラレル入力シリアル出力 (PISO) とか使ったことがないので、そのあたりも試してみたいです。でもその前に、マルチプレクサが必要かな。

過去記事一覧

論理回路に関するこれまでの記事をまとめておきました。
シフトレジスタ 74HC595 に関した記事も書いたことがあるので、こちらもご覧ください。


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