エレキ素人が何か考える（その９）：JKフリップフロップ


# ロジックIC（OR、NOT、AND）でJKフリップフロップをつくる
ロジックIC（OR、NOT、AND）を用いて、JKフリップフロップを作ったときの記録。

## 用いたロジックIC
- OR：[４回路ＯＲ　ＴＣ７４ＨＣ３２ＡＰ](https://akizukidenshi.com/catalog/g/gI-12877/)
- NOT：[６回路シュミットトリガインバーター　ＴＣ７４ＨＣ１４ＡＰ](https://akizukidenshi.com/catalog/g/gI-10923/)
- AND：[４回路ＡＮＤ　ＴＣ４０８１ＢＰ](https://akizukidenshi.com/catalog/g/gI-13732/)

いずれも秋月電子で購入。

### ピンアサイン
#### OR
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/8264b8af-f9a1-0aaf-e587-9326fffc439a.png)
#### NOT
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/9fa7395b-de8a-744a-349a-f702a9734624.png)
#### AND
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/8693e466-7ace-2f3c-39df-c9eb8a68b36a.png)
なぜか、ORやNOTと向きが一部異なる。

## 回路
### （本題の前に）SRフリップフロップ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/fdbb1bbe-3710-3d61-4ae6-6b3ac4d3151e.png)

### JKフリップフロップ
#### クロック（CLK）なし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/3d5f75b2-a431-4274-ce34-6f48f5d5d4ba.png)
真理値表は下記となる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/ed83c513-f9c2-40aa-58d6-c3e636d02246.png)
ではあるが、記事[「5. フリップフロップ」](https://edu.isc.chubu.ac.jp/naga/dec/dec5.html)にあるように（以下、引用、イタリック部分）

<I>
JK-FF, T-FF は出力を反転させる入力が存在するが、反転動作については次の点が 問題となる。例としてJK-FFで(1, 1)を入力した場合、それまでの出力が反転するが、 回路がフィードバックを含めて一周動作した後に、入力の(1, 1)が継続していると、 二周目の動作に入って再び反転してしまう。 本来は1回反転したらそこで値が固定されて欲しいが、この反転が連続して起こる現象は、 入力の(1, 1)が継続している間ずっと続く。この現象を 発振 、 レーシング と呼ぶ。
</I>

とのこと。Arduinoを用いて、次のようなソースコードを用いて確認。
```c++
#define INPUT_1   3
#define INPUT_2   4

void setup() {
  Serial.begin(9600);
  pinMode(INPUT_1, OUTPUT);
  pinMode(INPUT_2, OUTPUT);
  digitalWrite(INPUT_1, LOW);
  digitalWrite(INPUT_2, HIGH);
}

void loop() {
  if (Serial.available() > 0) {
    String data = Serial.readStringUntil('\n');
    int val = data.toInt();
    digitalWrite(INPUT_1, ((val & 0x01)? HIGH: LOW));
    digitalWrite(INPUT_2, ((val & 0x02)? HIGH: LOW));
  }
```
シリアルから入力した数値が、下記表となるように配線を実施。（なお、エラー入力は考慮していない。
|入力値|J (INPUT_1)|K (INPUT_2)|
|---|---|---|
|0|0|0|
|1|1|0|
|2|0|1|
|3|1|1|

”3”を入力したとき（J=1,K=1）の状況が下記写真であり（右は”Q#”に相当）、両者が点灯し、不安定な状況となっている。 
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/5b0d7038-e404-8072-481f-c3155eec8975.png", width=60%>

#### クロック（CLK）あり
次にクロックありの状況を擬似的に実現。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/f506e35a-14bf-005d-9ac4-12fe74c995e1.png)
真理値表は下記となる。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/74af4083-aeb5-f8f2-b22b-ecb65ffa8cf8.png", width=45%>
クロックあり時（上記表では立ち上がり時）のみ、出力されるもの。Arduinoと接続した状況は下記のとおり。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/ba6f14a8-8469-f60d-1a92-d69694896fa4.jpeg", width=60%>
ここではクロックの代わりとして、シリアル入力があったときに、”CLK=1”の状況を作り出した。ソースコードは下記のとおり。
```c++
#define INPUT_1   3
#define INPUT_2   4
#define CLOCK     10

void setup() {
  Serial.begin(9600);
  pinMode(INPUT_1, OUTPUT);
  pinMode(INPUT_2, OUTPUT);
  digitalWrite(INPUT_1, LOW);
  digitalWrite(INPUT_2, HIGH);
  pinMode(CLOCK, OUTPUT);
  digitalWrite(CLOCK, LOW);
}

void loop() {
  if (Serial.available() > 0) {
    String data = Serial.readStringUntil('\n');
    int val = data.toInt();
    digitalWrite(INPUT_1, ((val & 0x01)? HIGH: LOW));
    digitalWrite(INPUT_2, ((val & 0x02)? HIGH: LOW));
    digitalWrite(CLOCK, HIGH);
    delay(10);
    digitalWrite(CLOCK, LOW);
  }
```

”3”を入力したとき（J=1,K=1）の成功時の状況が下記となり、LEDの点灯が交互に行われている（QとQ#とが反転している）。
![S1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/5beb64d4-1ad7-bd65-f16c-a0d2cee1488f.gif)

ただし、下記のように、左のLEDが点灯後すぐに消灯してしまう（右のLEDは点灯のまま）状況が発生していた。
![F3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/12f1436d-0e36-0a0e-80f9-e6d00d3e3d77.gif)
プログラムを修正すれば、改善する可能性はあるだろう。

## ToDo
ハードウェアに限りなく近いFPGAを利用すれば、状況が改善するのでは、、と素人的には考えるので、近いうちに試してみる。