4 to 16 デコーダの検証 ～全加算器～

## 4 to 16デコーダ

元のネタは、別府 伸耕/Nobuyasu Beppu (リニア・テック)さんの下の記事です。

https://zep.co.jp/nbeppu/article/mz-cpu1738-da4/

4 to 16デコーダ
今回のROMには，アドレスとして“0”（2進数で“0000”）から“15”（2進数で“1111”）までの値が入力されます．このアドレス入力に応じてスイッチ・マトリクスの中から適切なスイッチを1つだけ選択し，データを出力することが求められます．この動作を実現するための回路が「4 to 16デコーダ」です．4 to 16デコーダは，「4ビットの入力信号を16本の出力信号に変換する回路」です．2進数の入力（4ビット）の値に応じて16本ある出力信号線のうち1本だけが“1”になり，それ以外の信号線は“0”になります．

![z3 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/941038/03051d39-0358-4b57-677b-895847f71d37.png)

つまり、４ビットを１６ビットの信号一本に絞ることが目的だったみたいなんですが、
私が、何を勘違いしたのか、４ビットCPUの回路だと思い込んでしまったので、
全加算器を構築するという魔改造をしています。

本来の用途とは違いますが、別府さんのお創りになられた回路図が正常動作することを確認できたという点で、成果があったのではないかと思っております。

```c:4 to 16デコーダを用いた全加算器の実験
#include <stdio.h>

int NOT(int a_in)
{
    if(1 == a_in)
        return 0;
    else if(0 == a_in)
        return 1;
}

int AND(int a_in, int b_in)
{
    return a_in & b_in;
}

int OR(int a_in, int b_in)
{
    return a_in | b_in;
}

int gate(int A1, int A2, int A3, int A4)
{
    int U[4];
    U[0] = 0;
    U[1] = 0;
    U[2] = 0;
    U[3] = 0;

    int L[4];
    L[0] = 0;
    L[1] = 0;
    L[2] = 0;
    L[3] = 0;

    int E[16];
    E[0] = 0;
    E[1] = 0;
    E[2] = 0;
    E[3] = 0;
    E[4] = 0;
    E[5] = 0;
    E[6] = 0;
    E[7] = 0;
    E[8] = 0;
    E[9] = 0;
    E[10] = 0;
    E[11] = 0;
    E[12] = 0;
    E[13] = 0;
    E[14] = 0;
    E[15] = 0;            

    if(1 == NOT(AND(A1, A2)))
        L[3] = 1;
    if(1 == NOT(AND(A2,NOT(A1))))
        L[2] = 1;
    if(1 == NOT(AND(A1, NOT(A2))))
        L[1] = 1;
    if(1 == NOT(AND(NOT(A1), NOT(A2))))
        L[0] = 1;
    if(1 == NOT(AND(A3, A4)))
        U[3] = 1;
    if(1 == NOT(AND(A4,NOT(A3))))
        U[2] = 1;
    if(1 == NOT(AND(A3, NOT(A4))))
        U[1] = 1;
    if(1 == NOT(AND(NOT(A3), NOT(A4))))
        U[0] = 1;


    if(1 == NOT(OR(L[3],U[3])))
        E[15] = 1;
    if(1 == NOT(OR(L[2],U[3])))
        E[14] = 1;
    if(1 == NOT(OR(L[1],U[3])))
        E[13] = 1;
    if(1 == NOT(OR(L[0],U[3])))
        E[12] = 1;

    if(1 == NOT(OR(L[3],U[2])))
        E[11] = 1;
    if(1 == NOT(OR(L[2],U[2])))
        E[10] = 1;
    if(1 == NOT(OR(L[1],U[2])))
        E[9] = 1;
    if(1 == NOT(OR(L[0],U[2])))
        E[8] = 1;

    if(1 == NOT(OR(L[3],U[1])))
        E[7] = 1;
    if(1 == NOT(OR(L[2],U[1])))
        E[6] = 1;
    if(1 == NOT(OR(L[1],U[1])))
        E[5] = 1;
    if(1 == NOT(OR(L[0],U[1])))
        E[4] = 1;

    if(1 == NOT(OR(L[3],U[0])))
        E[3] = 1;
    if(1 == NOT(OR(L[2],U[0])))
        E[2] = 1;
    if(1 == NOT(OR(L[1],U[0])))
        E[1] = 1;
    if(1 == NOT(OR(L[0],U[0])))
        E[0] = 1;

    int ans;

    for(int i=0;i<16;i++)
    {
        if(1 == E[i])
            ans = E[i];
    }
 
    return ans;
}

typedef struct ADDER
{
    int array;
    int A;
    int B;
    int S;
    int C;

} ADDER;

int fulladder(int A, int B, int *S, int *C)
{
    ADDER adder1, adder2;
    ADDER *p1_adder, *p2_adder;

    p1_adder = &adder1;
    p2_adder = &adder2;

    p1_adder->array = 0;
    p1_adder->A = A;
    p1_adder->B = B;
    p1_adder->S = 0;
    p1_adder->C = 0;

    if(0 == p1_adder->A && 0 == p1_adder->B)
    {
        p1_adder->S = 0;
        p1_adder->C = 0;
    }

    if(0 == p1_adder->A && 1 == p1_adder->B)
    {
        p1_adder->S = 1;
        p1_adder->C = 0;
    }

    if(1 == p1_adder->A && 0 == p1_adder->B)
    {
        p1_adder->S = 1;
        p1_adder->C = 0;
    }

    if(1 == p1_adder->A && 1 == p1_adder->B)
    {
        p1_adder->S = 0;
        p1_adder->C = 1;
    }

    printf("S1 = %d\n", p1_adder->S);
    printf("C1 = %d\n", p1_adder->C);


    p2_adder->array = 1;
    p2_adder->A = p1_adder->S;
    p2_adder->B = *C;
    p2_adder->S = 0;
    p2_adder->C = 0;

    if(0 == p2_adder->A && 0 == p2_adder->B)
    {
        p2_adder->S = 0;
        p2_adder->C = 0;
    }

    if(0 == p2_adder->A && 1 == p2_adder->B)
    {
        p2_adder->S = 1;
        p2_adder->C = 0;
    }

    if(1 == p2_adder->A && 0 == p2_adder->B)
    {
        p2_adder->S = 1;
        p2_adder->C = 0;
    }

    if(1 == p2_adder->A && 1 == p2_adder->B)
    {
        p2_adder->S = 0;
        p2_adder->C = 1;
    }

    printf("S2 = %d\n", p2_adder->S);
    printf("C2 = %d\n", p2_adder->C);


    *S = p2_adder->S;
    *C = OR(p1_adder->C, p2_adder->C);

	
    return 0;
}

int main(void)
{
    int s = 0;
    int c = 0;
    int *S = &s;
    int *C = &c;

    ADDER result[5];

	fulladder(0, 0, S, C);
    result[0].S = *S;
    result[0].C = *C;
	
	printf("%d", result[0].C);
	printf("%d\n", result[0].S);
	printf("%s\n", "-------");

    fulladder(1, 0, S, C);
    result[1].S = *S;
    result[1].C = *C;
	
	printf("%d", result[1].C);
	printf("%d\n", result[1].S);
	printf("%s\n", "-------");

	fulladder(0, 1, S, C);
    result[2].S = *S;
    result[2].C = *C;

	printf("%d", result[2].C);
	printf("%d\n", result[2].S);
	printf("%s\n", "-------");

	fulladder(1, 1, S, C);
    result[3].S = *S;
    result[3].C = *C;

	printf("%d", result[3].C);
	printf("%d\n", result[3].S);
	printf("%s\n", "-------");

	fulladder(1, 1, S, C);
    result[4].S = *S;
    result[4].C = *C;

	printf("%d", result[4].C);
	printf("%d\n", result[4].S);
	printf("%s\n", "-------");

	return 0;

```