1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TangNano9kにNNを実装して推論させる

Last updated at Posted at 2025-10-29

目的

tangnano9kにNNを実装できるようにしロボコンにおける活用方法を探す

使用するもの

TnagNano9k
GOWIN IDE

cで重みを作る

今回は学習はpc上で行い推論のみをFPGAで行う

ホップフィールドネットワーク

今回は最も古典的なNNであるホップフィールドネットワークを使う
5*5で表されたD J M Cを識別するものから始める
https://github.com/imaoca/neuroC/blob/main/neuro.c
から持ってきたこいつを試す(今後もここからプログラムリストを引用する)

c.c
#include <stdio.h>
int links[25*25];
int D[25]={
                 1, 1, 1, 1,-1,
                -1, 1,-1,-1, 1,
                -1, 1,-1,-1, 1,
                -1, 1,-1,-1, 1,
                -1, 1, 1, 1,-1
        };
int J[25]={
                 1, 1, 1, 1, 1,
                -1,-1,-1, 1,-1,
                -1,-1,-1, 1,-1,
                 1,-1,-1, 1,-1,
                 1, 1, 1,-1,-1
        };
int C[25]={
                -1, 1, 1, 1, 1,
                 1,-1,-1,-1,-1,
                 1,-1,-1,-1,-1,
                 1,-1,-1,-1,-1,
                -1, 1, 1, 1, 1
        };
int M[25]={	 1,-1,-1,-1, 1,
                 1, 1,-1, 1, 1,
                 1,-1, 1,-1, 1,
                 1,-1,-1,-1, 1,
                 1,-1,-1,-1, 1};

void show(int p[]){
        int i,j;
        for (i=0;i<5;i++){
         for(j=0;j<5;j++)
                if (p[i*5+j]>0) putchar('#');
                else
                        putchar(' ');
        putchar('\n');
        }
   putchar('\n');
}

void learn2(void){
  int i,j;
  for (i=0;i<25;i++)
     for(j=0;j<25;j++)
        links[i*25+j]=
	((D[i]==D[j])?1:-1)+
	((J[i]==J[j])?1:-1)+
	((C[i]==C[j])?1:-1)+
	((M[i]==M[j])?1:-1);
}

void hopfield(int inp[], int lin[]){
        int sum,i,j;
        for (i=0;i<25;i++){
                sum = 0;
                for(j=0;j<25;j++)sum=sum+(inp[j])*(lin[i*25+j]);
                inp[i]=(sum>=0)?1:-1;
        }
}



void main(void){
        int input[25]={
           -1, 1,-1, 1, 1,
           -1,-1,-1, 1,-1,
           -1,-1,-1, 1,-1,
           -1,-1,-1, 1,-1,
           -1, 1, 1,-1,-1
        };
	learn2();
        printf("example\n");
        show(input);
        printf("recognition\n");
        hopfield(input,links);
        show(input);
}

結果

画像のようになれば成功
image.png

重みを出す

学習でだした重みを見ます

c.c
#include <stdio.h>
int links[25*25];

int D[25]={
                 1, 1, 1, 1,-1,
                -1, 1,-1,-1, 1,
                -1, 1,-1,-1, 1,
                -1, 1,-1,-1, 1,
                -1, 1, 1, 1,-1
        };
int J[25]={
                 1, 1, 1, 1, 1,
                -1,-1,-1, 1,-1,
                -1,-1,-1, 1,-1,
                 1,-1,-1, 1,-1,
                 1, 1, 1,-1,-1
        };
int C[25]={
                -1, 1, 1, 1, 1,
                 1,-1,-1,-1,-1,
                 1,-1,-1,-1,-1,
                 1,-1,-1,-1,-1,
                -1, 1, 1, 1, 1
        };
int M[25]={	 1,-1,-1,-1, 1,
                 1, 1,-1, 1, 1,
                 1,-1, 1,-1, 1,
                 1,-1,-1,-1, 1,
                 1,-1,-1,-1, 1};



void learn2(void){
  int i,j;
  for (i=0;i<25;i++)
     for(j=0;j<25;j++)
        links[i*25+j]=links[i*25+j]+((D[i]==D[j])?1:-1)+((J[i]==J[j])?1:-1)+((C[i]==C[j])?1:-1)+((M[i]==M[j])?1:-1);
}

void listlinks(void){
    for (int i = 0; i < 625; i++) {
        int val = links[i];  // 整数としてそのまま出力
        printf("%d\n", val);
    }
}

int main(void){
	learn2();
	listlinks();
}

結果

画像みたいになればOK
image.png

Cで推論だけする

さっき出力した重みを使い推論のみを行う

omomi.c
#include <stdio.h>

// 学習済みの重み行列(links)を直接定義
int links[25*25] = {
    4, 0, 0, 0, 0, -2, 2, -2, 2, 2, -2, 0, 0, 0, 2, 0, 0, -2, 0, 2, 2, 0, 0, -2, -2, 0, 4, 4, 4, 0, -2, -2, -2, -2, -2, -2, 0, -4, 0, -2, 0, 0, -2, 0, -2, -2, 4, 4, 2, -2, 0, 4, 4, 4, 0, -2, -2, -2, -2, -2, -2, 0, -4, 0, -2, 0, 0, -2, 0, -2, -2, 4, 4, 2, -2, 0, 4, 4, 4, 0, -2, -2, -2, -2, -2, -2, 0, -4, 0, -2, 0, 0, -2, 0, -2, -2, 4, 4, 2, -2, 0, 0, 0, 0, 4, 2, -2, -2, 2, -2, 2, -4, 0, 0, -2, 4, -4, -2, 0, -2, 2, 0, 0, -2, 2, -2, -2, -2, -2, 2, 4, 0, 0, 0, 0, 4, -2, 2, -2, 0, 2, -2, 0, -2, 0, 0, -2, -2, 0, 4, 2, -2, -2, -2, -2, 0, 4, 0, 0, 4, 0, 2, 2, -2, 4, -2, 2, 0, -2, 4, 0, -2, -2, 0, 0, -2, -2, -2, -2, -2, 0, 0, 4, 0, 0, 0, 2, 2, 2, 0, -2, 2, 4, 2, 0, 0, -2, -2, 0, 0, 2, -2, -2, -2, 2, 0, 0, 0, 4, 0, 0, -2, 2, 2, 0, 2, -2, 0, 2, 0, 4, -2, -2, -4, 0, 2, -2, -2, -2, -2, 0, 4, 0, 0, 4, 0, 2, 2, -2, 4, -2, 2, 0, -2, 4, 0, -2, -2, 0, 0, -2, -2, -2, -2, 2, 4, 0, 0, 0, 0, 4, -2, 2, -2, 0, 2, -2, 0, -2, 0, 0, -2, -2, 0, 4, 0, 0, 0, 0, -4, -2, 2, 2, -2, 2, -2, 4, 0, 0, 2, -4, 4, 2, 0, 2, -2, 0, 0, 2, -2, 0, -4, -4, -4, 0, 2, 2, 2, 2, 2, 2, 0, 4, 0, 2, 0, 0, 2, 0, 2, 2, -4, -4, -2, 2, 0, 0, 0, 0, 0, -2, -2, 2, 2, -2, -2, 0, 0, 4, -2, 0, 0, 2, 4, -2, 2, 0, 0, -2, -2, 2, -2, -2, -2, -2, 0, 4, 0, 0, 4, 0, 2, 2, -2, 4, -2, 2, 0, -2, 4, 0, -2, -2, 0, 0, 0, 0, 0, 0, 4, 2, -2, -2, 2, -2, 2, -4, 0, 0, -2, 4, -4, -2, 0, -2, 2, 0, 0, -2, 2, 0, 0, 0, 0, -4, -2, 2, 2, -2, 2, -2, 4, 0, 0, 2, -4, 4, 2, 0, 2, -2, 0, 0, 2, -2, -2, -2, -2, -2, -2, 0, 0, 4, 0, 0, 0, 2, 2, 2, 0, -2, 2, 4, 2, 0, 0, -2, -2, 0, 0, 0, 0, 0, 0, 0, -2, -2, 2, 2, -2, -2, 0, 0, 4, -2, 0, 0, 2, 4, -2, 2, 0, 0, -2, -2, 2, -2, -2, -2, -2, 0, 4, 0, 0, 4, 0, 2, 2, -2, 4, -2, 2, 0, -2, 4, 0, -2, -2, 0, 0, 2, -2, -2, -2, 2, 0, 0, 0, 4, 0, 0, -2, 2, 2, 0, 2, -2, 0, 2, 0, 4, -2, -2, -4, 0, 0, 4, 4, 4, 0, -2, -2, -2, -2, -2, -2, 0, -4, 0, -2, 0, 0, -2, 0, -2, -2, 4, 4, 2, -2, 0, 4, 4, 4, 0, -2, -2, -2, -2, -2, -2, 0, -4, 0, -2, 0, 0, -2, 0, -2, -2, 4, 4, 2, -2, -2, 2, 2, 2, -2, 0, 0, 0, -4, 0, 0, 2, -2, -2, 0, -2, 2, 0, -2, 0, -4, 2, 2, 4, 0, -2, -2, -2, -2, 2, 4, 0, 0, 0, 0, 4, -2, 2, -2, 0, 2, -2, 0, -2, 0, 0, -2, -2, 0, 4, 
};

void show(int p[]) {
    int i, j;
    for (i = 0; i < 5; i++) {
        for (j = 0; j < 5; j++)
            putchar(p[i * 5 + j] > 0 ? '#' : ' ');
        putchar('\n');
    }
    putchar('\n');
}

void hopfield(int inp[], int lin[]) {
    int sum, i, j;
    for (i = 0; i < 25; i++) {
        sum = 0;
        for (j = 0; j < 25; j++)
            sum += inp[j] * lin[i * 25 + j];
        inp[i] = (sum >= 0) ? 1 : -1;
    }
}

int main(void) {
    int input[25] = {
        -1, 1,-1, 1, 1,
        -1,-1,-1, 1,-1,
        -1,-1,-1, 1,-1,
        -1,-1,-1, 1,-1,
        -1, 1, 1,-1,-1
    };

    printf("example\n");
    show(input);

    printf("recognition\n");
    hopfield(input, links);
    show(input);

    return 0;
}

結果

画像のようになればOK
image.png

このコードをverilogに置き換えていく

その前に

verilogで読み込ませるときの形で重みを出力しておく....と思ったが
https://github.com/imaoca/neuroC/blob/main/links.txt
用意されていたのでこちらをありがたく使わさせてもらう

Verilog

参考

コード

neuro.v
module neuro (input rst,input clk,input [3:0]btn, output reg [4:0] led);
  reg [24:0] neuros;
  reg signed[7:0] links[624:0];
  reg[4:0] i=0,jj=0;
  reg signed [7:0]sum;
  reg [24:0]count12;

  always @(posedge(clk))count12 = count12 + 1;
  integer k,m;
  always @(posedge(clk))begin 
	if (rst==0)  begin i = 0;neuros = 25'b0011101001010000100011111;led <= 5'b11110; end //0111010011100100001001110D 0011101001010000100011111J 1111000001000010000111110C 1000110001101011101110001M
	if ((btn[0]==0)&&(i==0))begin
        for (k=0;k<25;k=k+1) begin 
            sum=0;
            for (m=0;m<25;m=m+1)
                sum = sum + ((neuros[m]==1)?links[(k<<4)+(k<<3)+k+m]:(-links[(k<<4)+(k<<3)+k+m]));
        neuros[k]=(sum>0)?1:0;
        end
		i = 1;
        if(i == 1)begin led <= {neuros[9:5]}; end //ここでLEDの見る場所をきめてうまくいっているか確認する
	end
 end
always @(posedge(clk))if (rst==0) begin `include "links.txt" end
endmodule
neuro.cst
IO_LOC "led[4]" 15;
IO_LOC "led[3]" 14;
IO_LOC "led[2]" 13;
IO_LOC "led[1]" 11;
IO_LOC "led[0]" 10;

IO_LOC "btn[0]" 3;
IO_LOC "clk" 52;
IO_LOC "rst" 4;

これで書きこめば動くはずです
画像はうまくいったときのもの
image.png

書きこみ方

参考まとめ

https://monoist.itmedia.co.jp/mn/articles/2403/11/news023_2.html
https://github.com/imaoca/neurosFPGA/blob/main/neuro9k/src/neuro9k.v
https://github.com/imaoca/neuroC/blob/main/links.txt
https://zenn.dev/nihinihikun/articles/87066301959b48

おわりに

当初は学習も行うつもりだったが論理合成の際にPCのメモリが足りなくなりクラッシュしたためあきらめた(友人のPCでためしたらメモリは60以上使われていた...)
目的である活用方法を探す、はまだ達成されていないのでカメラからの入力をNN推論して画像認識に挑戦してみるつもりです
言葉足らずなとこらが多いため今後追記していきます
読んでくださりありがとうございました

1
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?