2017-11-09 10 views
0

コンテキスト:
私はコンピュータ工学の男です。私は学校に通っており、これは私の上級プロジェクトの一部です。私は、私のグループによって作成された電子ボードゲームで使用するためにFPGAをプログラムしようとしています。 FPGAは、すべてのロジックを制御するRaspberry PiのIOエクステンダです。下記のVerilogコードは、アルテラのMax V 570 devkit上で実行され、本番用ユニットのMax V 40に移行する予定です。各FPGAは4つのゲームタイルのグループを制御し、最終製品には4つのタイルグループが存在します。コンプライアントSCIの主要な予期しない出力でFPGAをプログラミングする際の問題

問題:
は、私は我々のシステムでは(今のLED)MOSFETを制御するためにラズベリーパイとのインタフェースになるFPGAを作成しています。私が午前の問題は関係なく、私がタイルに送って、どのコマンド、LEDは、いつものようにトグルされていない、ということです:

tile0のために、唯一の0番目のLEDは第一LEDが切り替わります、tile1ため
を切り替えます(
https://drive.google.com/open?id=0B7P773tnBnRybHhGRmZMX3hScGFrNXpKUDN2c0tBbkFZaTVJ
それぞれのLED決勝を無視:
tile2のために、唯一の第二LEDはtile3のために、唯一の第三LEDがここ

はアクションでこのの写真へのリンクです切り替わります
を切り替えます容量性センサから入力される)、

これは、LEDトグルコマンド(下のコードでは2'b11)とソレノイドのトグル(下のコードでは2'b01)に該当します。

アルテラModelSimでのシミュレーションでは、すべてが完全に機能します!しかし、すべてがブレッドボードに接続されて、私は上記の状況を参照してください。
は、私が最初に問題を考え、問題に

私の考えは、私はから読んでいた同じレジスタに割り当てるとあったが、私はそれから割り当て、レジスタを読み取るために(...無計画に)別のステップを追加しましたが、私は悪い動作を見た(LEDはトグルしない)。助けて! :)ここで

は私のverilogコードです:誰もが私に正確に40のLE以下にこれを削減する方法についての指針を与えることができれば

module comm_protocol(clock, bus, t0, t1, t2, t3, t0cap, t1cap, t2cap, t3cap, capOut); 

parameter [1:0] my_address = 2'b11; 


input clock; 
input [3:0] bus; 

output reg [4:0] t0; 
output reg [4:0] t1; 
output reg [4:0] t2; 
output reg [4:0] t3; 

input wire t0cap, t1cap, t2cap, t3cap; 
output reg capOut; 

reg start; 
reg [1:0] tickCounter; 

reg gotFpgaAddress; 
reg [1:0] fpgaAddress; 
reg[1:0] tileAddress; 

reg gotCommand; 
reg [3:0] command; 

initial begin 

    start <= 0; 

    t0 <= 5'b11111; 
    t1 <= 5'b11111; 
    t2 <= 5'b11111; 
    t3 <= 5'b11111; 

end 


always @ (posedge clock) begin 

    // check if we have recieved the start condition, which is just a positive edge on the clock 
    if (~start) begin 

     start <= 1; 
     tickCounter <= 0; 
     gotFpgaAddress <= 0; 
     gotCommand <= 0; 

    end 
    else begin // we have received the start condition, so continue into the logic 

     // increment the counter 
     // this counter controls when a reset of the logic is performed 
     // the entire protocol should take place in 4 cycles, so when our counter hits 3 we are done 
     tickCounter <= tickCounter + 1; 
     if (tickCounter == 3) begin 

      start <= 0; 

     end 
     else begin // no reset, continue into logic 

      // here, we will read the address of the fpga the pi is talking to 
      // first check if we have recieved the address or not 
      if (~gotFpgaAddress) begin 

       fpgaAddress <= bus[3:2]; //[3:0]; 
       tileAddress <= bus[1:0]; 

       gotFpgaAddress <= 1; 
       //gotTileAddress <= 1; 

      end 
      else begin // we got the address, now compare it to see if it matches our address 

       if (fpgaAddress == my_address) begin 

        // the message is intended for us, so next we check if the command has been received 
        if (~gotCommand) begin 

         //tileAddress <= bus[3:0]; 
         command <= bus; 
         gotCommand <= 1; 

        end 
        else begin // we have received the command, now decode it and perform the action 

         // decode the command that has been sent 
         // leading 11xx : toggle an led specified by the 2 least significant bits 
         // leading 00xx : read from the capactive sensor and write it onto the bus 
         // leading 01xx : toggle the solenoid for the popup 

         // implement logic to toggle leds 
         if (command[3:2] == 2'b11) begin 

          // route to appropriate tile 
          case (tileAddress) 

           // tile 0 
           2'b00: begin 
            case (command[1:0]) 
             2'b00: t0[0] <= ~t0[0]; 
             2'b01: t0[1] <= ~t0[1]; 
             2'b10: t0[2] <= ~t0[2]; 
             2'b11: t0[3] <= ~t0[3]; 
            endcase 
           end 
           // tile 1 
           2'b01: begin 
            case (command[1:0]) 
             2'b00: t1[0] <= ~t1[0]; 
             2'b01: t1[1] <= ~t1[1]; 
             2'b10: t1[2] <= ~t1[2]; 
             2'b11: t1[3] <= ~t1[3]; 
            endcase 
           end 
           // tile 2 
           2'b10: begin 
            case (command[1:0]) 
             2'b00: t2[0] <= ~t2[0]; 
             2'b01: t2[1] <= ~t2[1]; 
             2'b10: t2[2] <= ~t2[2]; 
             2'b11: t2[3] <= ~t2[3]; 
            endcase 
           end 
           // tile 3 
           2'b11: begin 
            case (command[1:0]) 
             2'b00: t3[0] <= ~t3[0]; 
             2'b01: t3[1] <= ~t3[1]; 
             2'b10: t3[2] <= ~t3[2]; 
             2'b11: t3[3] <= ~t3[3]; 
            endcase 
           end 

          endcase 

         end 
         // implement logic to read from the capacitive sensor and write it onto the bus 
         else if (command[3:2] == 2'b00) begin 

          case (tileAddress) 

           2'b00: capOut <= t0cap; 
           2'b01: capOut <= t1cap; 
           2'b10: capOut <= t2cap; 
           2'b11: capOut <= t3cap; 

          endcase 

         end 
         // implement logic to toggle the solenoid 
         else if (command[3:2] == 2'b01) begin 

          case (tileAddress) 

           2'b00: t0[4] <= ~t0[4]; 
           2'b01: t1[4] <= ~t1[4]; 
           2'b10: t2[4] <= ~t2[4]; 
           2'b11: t3[4] <= ~t3[4]; 

          endcase 

         end 

        end 

       end 

      end 

     end 

    end  

end 


endmodule 

BONUS
は現在、私は、42個のロジック・エレメントを消費しています、私は永遠に感謝します!ではない大したことは、80の要素マックスVは、問題を発見MaxV40

+0

fpgaのコンパイル中に警告が表示されましたか?私には疑わしい場所はほとんどありません。 1)正しいリセットがない。初期ブロックがFPGAで動作していない可能性があります。 2)ポートを 'reg'として宣言してください。必ずしも正しく動作する概念ではありません。より高いレベルの階層では接続の問題があり、シミュレーション/ FPGAの動作の違いがあるかもしれません。 – Serge

+0

これは、2分間のコーヒーブレークで読み込むコードがたくさんあります。 1つの明白なことは 'コマンド'です - あなたはそれをいつ割り当てるのですか、それをいつ読むのですか? 2つの異なるクロックサイクルに入っていますか?それがうまくいくと思いますか?もしそうなら、なぜですか?タイミングダイアグラムを描き、ダイアグラムからコードを作成します。あなたのコントロールの流れは間違っています。また、非ブロッキング代入( '<=')が何をするのかを理解してください。 – EML

+0

@ Serge私は警告を受け取りますが、なぜこれが正しく機能していないのかの手掛かりはありません。ちょうどタイミングファイルが欠けているなどです。 – user1152415

答えて

0

あなたのPythonコードで問題が見つかりました。 1つのことは、バスをサンプリングするための修飾子としてもう1つの入力ピンを追加することです。それ以外の場合は、すべてのFPGAが完全に同期していることを確認する必要があります。ボーナスの質問には今

変更がなければ、あなたのコードのいずれかの動作が、あなたは、FSMへtickCounterを変換することにより、3つのプ(startgotFpgaAddress、およびgotCommand)と論理ゲートのほんの少しを排除することができます。私はtickCounterが0であることに気がつきました。あなたは常に初期状態/リセット状態です。それが1のとき、あなたは住所を得ています。それが2の場合、ターゲットのfpgaアドレスであればコマンドを収集することができます。そして、それが3であるとき、目標のfpgaアドレスでLEDをトグルします。

localparam INIT=2'b0, GETADDR=2'b01, GETCMD=2'b10, TOGGLELED=2'b11; 
reg [1:0] state; 

reg [1:0] fpgaAddress; 
reg [1:0] tileAddress; 
reg [3:0] command; 

initial begin 
    state = INIT; // Note: initial blocks should use blocking statements 
    t0 = 5'b11111; 
    t1 = 5'b11111; 
    t2 = 5'b11111; 
    t3 = 5'b11111; 
end 

always @ (posedge clock) begin 
    case(state) 
    INIT : 
     begin 
     state <= GETADDR; 
     // technically this is a dummy state, but needed to match behavior 
     end 
    GETADDR : 
     begin 
     state <= GETCMD; 
     fpgaAddress <= bus[3:2]; 
     tileAddress <= bus[1:0]; 
     end 
    GETCMD : 
     begin 
     state <= TOGGLELED; 
     /* No output is effected in this state, 
     * so it doesn't matter what the address is. 
     * Preventing assignment to command would add logic. 
     */ 
     command <= bus; 
     end 
    TOGGLELED : 
     begin 
     state <= INIT; 
     // Here we care about the address 
     if (fpgaAddress == MY_ADDRESS) begin 
      // ... your assignments to t0-t3 here ... 
      /* There are tricks to reduce the number of lines of code here, 
      * but nothing I can immanently think of that will reduce gate count. 
      */ 
     end 
     end 
    endcase 
end 

本当に面積を圧迫したい場合は、INITGETCMD状態を除去することによって、二つの状態にそれをダウンさせることができます。 busTOGGLELEDの状態のcommandになりました。また、これによりデザインが4サイクルから2サイクルに変更されます。だから刺激(あなたのpythonコード)も変更する必要があります。

上記の修飾子入力ピンを追加すると、状態割り当て(例:if (start_fsm) begin state <= NEXT_STATE ; /*... other stuff ...*/ end else begin state <= CURRENT_STATE; end)の調整が行われます。


もう1つのトピックでは、モジュールヘッダーが非ANSIと呼ばれるやや古くなったスタイルで書かれています。 Verilog-1995ではより厳密なバージョンのNon-ANSIが必要です(output reg[4:0] t0;の代わりにoutput [4:0] t0;reg[4:0] t0;)が、Verilog-2001が広くサポートされて以来、人気を失っています。現代のヘッダースタイルはANSIと呼ばれます。 ANSIスタイルでは、ポート順序、方向、および型を同じ行に宣言します(非ANSIでは2〜3の別々の行が必要です)。それはタイプミスの少ないクリーナーです。

+0

あなたは素晴らしいです!私は数日後にあなたの提案を実装するつもりです、私はあなたに何が起こるかをお知らせします! – user1152415

+0

最終結果:37 LEが使用されました!あなたはちょうど80要素MaxVを購入することから私を救った.... 0.7USD *ゲームボードあたり4枚のfpga * 15ゲームボード= 42USDを保存!あなたに美しいピンクのバニーの岩! – user1152415

0

ため息

よりもわずか70セント以上である、それはPythonのコードは全部こいつを制御していました。私は、アドレスを送信するための変数を再利用し、誤ってコマンドとして送信しました...

しかし、それは働く!