FPGAでディスプレイに絵を描く

 FPGAでアナログ映像端子であるVGAに信号を送って絵を表示する回路に挑戦した。

下図みたいな信号を生成する回路を作った。



赤丸で囲ったところが水平の同期信号。各区切りがディスプレイの横一列に対応する。


これをズームアウトすると、垂直方向の同期信号も見える。これで1画面の描画が終わる。

ディスプレイの左上から右へ描画していくからその間にRGBの値を信号として与えれば

描画できる。RGBの波形を見ると0000と1111が交互に並んでいるから

左半分黒、右半分白で表示される。意外と簡単に出来た。
ジャジャガッチ | FPGA | 20:00 | comments(0) | trackbacks(0) |

FPGA

 本格的にFPGAで遊び始めたのでFPGAカテゴリを作った。

最初にFPGAとはどんなものか説明しておく。

今世の中で幅をきかせているのはデジタル回路。

値は0か1しかなくて、例えばNOT回路は入力を反転する。

AND回路なら二つの入力が1のときだけ出力が1になる。

こういう回路を組み合わせて複雑な回路を作ると面白いことが出来る。例えば

入力→出力と書くとして

(0,0)→(0,0)
(0,1)→(0,1)
(1,0)→(0,1)
(1,1)→(1,0)

という関係を持つようにAND回路とかNOT回路とかを組み合わせられれば

その回路は二進数の足し算回路になる。

で、FPGAはPCを通して任意のデジタル回路を焼けるICのこと。

PCに設計図を書くだけだからハンダ付けしなくてもいいし、何度でも焼けるから

失敗しても大丈夫。

すばらしい。

もっとすばらしいのは簡単に複雑な回路を作れること。

AND回路とかをグラフィカルに配置して設計することも出来るけど、

コードを書くことによっても設計できる。

例えば

入力はAとBで、出力はCとD。
これこれこういう条件のときCは1でDは0になる。
・・・

みたいに得たい結果を書いていけば自動的にそれを実現する回路を生成してくれる。

FPGAを始めてまだあまり経っていない僕でさえ50行くらいコードを書けば、




こういうとっても複雑な回路を作れます。

記述言語はVHDLとVerilog HDLがよく知られていて、VHDLから入ったけど

Verilog HDLに変えました。C言語ライクな言語らしいので。

ジャジャガッチ | FPGA | 19:52 | comments(0) | trackbacks(0) |

ModelSim

 今日はVHDLの勉強。

大分分かってきたのでModelSimというシミュレーションツールを落としてきた。

これで書いたコードのテストが出来る。

自作するCPUだけど丸パクリじゃ面白くないので少しは自分色を入れたいと思う。

とりあえずCPUに必要な要素を少しずつコーディングしてはシミュレーションを繰り返すかな。

VHDLの本を読破する元気はないから、そうやって必要なところを勉強していきたい。
ジャジャガッチ | 電子工作 | 00:14 | comments(0) | trackbacks(0) |

FPGA覚書

 今日からFPGAを本格的に始めることにした。

まずはコンパイルからということで覚書

CPUを作ることを目標にする。
ジャジャガッチ | 電子工作 | 14:44 | comments(0) | trackbacks(0) |

SFCコントローラ改造(6)

 テキストファイルを読み込んで複雑な動作をすることが可能になりました。

あと、書き忘れてましたが基板の表面はすこし削らないと保護されているので導線が

露出しないことに注意。

簡単なレポートを作成しました。→SFC.pdf
ジャジャガッチ | 電子工作 | 12:56 | comments(0) | trackbacks(0) |

SFCコントローラ改造(5)

 今回はPC側のプログラムの話。

前に書いたとおり、WindowsAPIでもシリアル通信プログラムを書くのはそんなに難しくない。

でもGUIを手打ちで作るのが面倒なのでやっぱりC++/CLIを使います。

大事なところだけコードを抜き出しておく。

private: System::Void R_Click(System::Object^  sender, System::EventArgs^  e) {
                serialPort1->Open();
                array<wchar_t>^ buffer = gcnew array<wchar_t>(2);
                buffer[0] = 'R';
                serialPort1->Write(buffer,0,1);
                serialPort1->Close();
         }
private: System::Void DELAY_B_Click(System::Object^  sender, System::EventArgs^  e) {
            serialPort1->Open();
            int delay;
            int DELAY[3];
           
            delay = System::Int32::Parse(DELAY_T->Text);
            DELAY[0] = delay/100;
            DELAY[1] = (delay - DELAY[0]*100)/10;
            DELAY[2] = (delay - DELAY[0]*100 - DELAY[1]*10);
            array<wchar_t>^ buffer = gcnew array<wchar_t>(10);
            buffer[0] = 'Z';
            buffer[1] = (wchar_t)DELAY[0];
            buffer[2] = (wchar_t)DELAY[1];
            buffer[3] = (wchar_t)DELAY[2];
            serialPort1->Write(buffer,0,1);
            Sleep(1000);
            serialPort1->Write(buffer,1,1);
            Sleep(1000);
            serialPort1->Write(buffer,2,1);
            Sleep(1000);
            serialPort1->Write(buffer,3,1);
            serialPort1->Close();

           
         }




これにテキストファイルを読み込んで複雑なキー操作を実行する機能をつけたい。

ジャジャガッチ | コンピュータ | 14:45 | comments(0) | trackbacks(0) |

SFCコントローラ改造(4)

 今回はマイコン側のプログラムの話。

作りたかったのは、PCから'd'という文字を受け取ると下ボタンに0Vをかける

ようなプログラム。

また、0Vをかける時間の設定もPCから行いたい。

書いたプログラムは下。

#include <pic.h>

__CONFIG(0x3F72);

#define MY_SPBRG 25
#define XON 17
#define XOFF 19
#define _XTAL_FREQ 4000000

unsigned char x;//XON,XOFFを格納
unsigned char buf[16];//バッファ
unsigned char wp = 0;//書き込み位置
unsigned char rp = 0;//読み出し位置
unsigned char n;//データ数
int delay = 10;//ディレイ繰り返し数
int SET = 0;//ディレイ繰り返し数設定用

void initialize(void);
void KEY_DOWN(void);

void main(void)
{
    int i;
   
    ADCON1=0x07;//AD変換オフ。
    TRISA=0;
    TRISB=0;
    TRISC = 0b11000000;
    TRISD=0;
    TRISE=0;

    //ポートの初期化
    PORTA = 0xFF;
    PORTB = 0xFF;
    RE0 = 1;

    initialize();
   
    GIE = 1;//受信開始
    TXREG = XON;

while(1) KEY_DOWN();
}

void initialize(void)
{
    SPBRG = MY_SPBRG;
    TXSTA = 0b00100100;
    RCSTA = 0b10010000;
    RCIE = 1;
    PEIE = 1;
}


//受信割り込み 相手からXON/XOFFを受信する
void interrupt entry(void)
{
    unsigned char c;
    if(RCIF)
    {
        c = RCREG;
        if(c==XON||c==XOFF)
        {
            x = c;
            return;
        }
        buf[wp++] = c;//バッファに受信データを格納
        n++;
        if(wp==16) wp = 0;
    }
}

void KEY_DOWN(void)
{
    int i;   
   
    while(n==0);//データ受信を待つ
    RCIE  = 0;//受信割り込み禁止
   
   

   
    switch(buf[rp])
    {
        case 'u':
        RA0 = 0;
        for(i=1;i<=delay;i++)__delay_ms(100);
        RA0 = 1;
        break;
       
        case 'l':    
        RA1 = 0;
        for(i=1;i<=delay;i++)__delay_ms(100);
        RA1 = 1;
        break;
       
        case 'd':    
        RA2 = 0;
        for(i=1;i<=delay;i++)__delay_ms(100);
        RA2 = 1;
        break;
       
        case 'r':    
        RA3 = 0;
        for(i=1;i<=delay;i++)__delay_ms(100);
        RA3 = 1;
        break;
       
        case 'A':    
        RB3 = 0;
        for(i=1;i<=delay;i++)__delay_ms(100);
        RB3 = 1;
        break;
       
        case 'B':    
        RB4 = 0;
        for(i=1;i<=delay;i++)__delay_ms(100);
        RB4 = 1;
        break;
       
        case 'X':    
        RB5 = 0;
        for(i=1;i<=delay;i++)__delay_ms(100);
        RB5 = 1;
        break;
       
        case 'Y':    
        RB6 = 0;
        for(i=1;i<=delay;i++)__delay_ms(100);
        RB6 = 1;
        break;
       
        case 'L':    
        RA4 = 0;
        for(i=1;i<=delay;i++)__delay_ms(100);
        RA4 = 1;
        break;
       
        case 'R':    
        RA5 = 0;
        for(i=1;i<=delay;i++)__delay_ms(100);
        RA5 = 1;
        break;
       
        case 'S':    
        RB7 = 0;
        for(i=1;i<=delay;i++)__delay_ms(100);
        RB7 = 1;
        break;
       
        case 's':    
        RE0 = 0;
        for(i=1;i<=delay;i++)__delay_ms(100);
        RE0 = 1;
        break;
       
        case 'Z'://ディレイ繰り返し数設定モード
        SET = 1;
        goto A;
        break;
    }
   
    switch(SET)
    {
        case 1:
        delay = 0;
        delay += buf[rp]*100;
        SET++;
        break;
       
        case 2:
        delay +=buf[rp]*10;
        SET++;
        break;
       
        case 3:
        delay += buf[rp];
        SET = 0;//ディレイ繰り返し数設定モードを抜ける
        break;
    }
   
A:   
    rp++;
    n--;
    if(rp==16) rp = 0;
    RCIE = 1;

}


ジャジャガッチ | コンピュータ | 14:42 | comments(0) | trackbacks(0) |

WIN32APIでシリアル通信

 .net系の言語を使うとシリアル通信はとても簡単。

でもWindowsAPIを使ってもそんなに難しくない。

下のプログラムを実行するとCOM9を開いて'r'という文字を送信する。

#include <windows.h>
#include <stdio.h>

unsigned long BytesWritten;
unsigned long BytesRead;
HANDLE PortHandle;
DCB dcb;

void InitAndOpen(const char *port);
void Send(unsigned char data);
void Receive(unsigned char *data);
void Close(void);

int main()
{
    char port[10] = "COM9";
    unsigned char *data;
    data = (unsigned char*)malloc(5);

    InitAndOpen(port);
    Send('r');
    Sleep(3000);
   
    Close();
    free(data);
    return 0;
}

void InitAndOpen(const char* port)
{
    PortHandle = CreateFile(port,
                            GENERIC_READ | GENERIC_WRITE,
                            0,
                            0,
                            OPEN_EXISTING,
                            FILE_ATTRIBUTE_NORMAL,
                            0);

    //シリアル通信の設定はDCB構造体を通じて行う。ここでDCB構造体の設定
    ZeroMemory(&dcb,sizeof(dcb));
    dcb.DCBlength = sizeof(dcb);
    BuildCommDCB("9600,n,8,1",&dcb);

    SetCommState(PortHandle,&dcb);
}

void Close(void)
{
    CloseHandle(PortHandle);
}

void Send(unsigned char data)
{
    unsigned char *pdata;
    pdata = &data;

    WriteFile(PortHandle,
              pdata,
              1,
              &BytesWritten,
              NULL);
}

void Receive(unsigned char *data)
{
    ReadFile(PortHandle,
             data,
             1,
             &BytesRead,
             NULL);
}
ジャジャガッチ | コンピュータ | 14:38 | comments(0) | trackbacks(0) |

ボルテージフォロア

 SFCコントローラ改造のときにボルテージフォロアを入れたと書いた。

この回路最近仕事で知った。

すごく便利。

例えばある回路Bに5Vを加えたいとする。

そこで回路Aを作成して回路中に5Vの点を作ったとする。

で、AとBを直接接続すればBに5Vを入力できる。

でも実際はそんなにうまくいかない。

AとBをつなげるとA+Bという回路になって電流の流れが変わり、

5Vの点は5Vでなくなる。

じゃあ、どうすればよいかというと

A-ボルテージフォロア-B

といった感じで間にボルテージフォロアを入れるとちゃんと5Vを入力できる。

AとBの回路の分離が出来るのだ。

便利。

ジャジャガッチ | 電子工作 | 14:32 | comments(0) | trackbacks(0) |

SFCコントローラ改造(3)

 回路が完成した。

スーパーファミコンのコントローラの基板は下の写真。



ICから各ボタンに導線がつながっていて、普段は5Vになっている。

ボタンが押されるとこの導線がGNDと導通して0Vになる。

これによってボタンが押されたという判断がなされる。



その導線にマイコンをつないで5Vにすればボタンが押されていない状態、0Vにすれば

ボタンが押された状態となる。作成した回路の写真は下。



マイコンはPIC16F877Aを使った。

クロックは最初セラロックを使ったのだがこれが原因でうまく動かなかった。

水晶振動子に変えたところ正常に動いた。

上の写真の右3つのICはオペアンプ。1つのICに4つのオペアンプが入っているので

計12のオペアンプを使っている。

最初はPICとコントローラを直接接続していたのだがうまくうごかなかったので

ボルテージフォロアを間に入れて解決した。
ジャジャガッチ | 電子工作 | 14:18 | comments(0) | trackbacks(0) |
1/1PAGES | |

05
--
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
--
>>
<<
--
PR
RECOMMEND
RECENT COMMENT
MOBILE
qrcode
OTHERS
Since 2013/09/17
LATEST ENTRY
CATEGORY
ARCHIVE
LINKS
PROFILE
SEARCH