1

k-nearest-neighbor コード (MATLAB) を Verilog に移植して、設計で使用し、最終的に FPGA ボードに配置できるようにしようとしています。Null 行列と恒等行列の作成、2D 行列の乗算などは事前に作成された関数によって便利に処理されるため、MATLAB ではコードとその操作がかなり単純になりました。私は Verilog で同じことをしようとしていますが、'for' ループは並列構造でのみ使用され、非常に効率的ではないため (そうですか?) 使用しません。私は 1 次元配列を処理できますが、効率的な (または少なくともハードウェアで得られるのと同じくらい効率的な) 2D 行列について何も考えられないようです。どんなアドバイスも役に立ちます。

前もって感謝します!!

4

2 に答える 2

0

alwaysfor ループはあなたの友人ですが、シーケンシャル コード ( / initial/ function/ )ではなく、生成で使用される場合のみtaskです。シーケンシャル for ループは、注意しないと複雑なハードウェアにつながる可能性があります。

これは基本的に他の言語と同じ方法でコーディングできますが、モジュール ポートを介して配列を渡すことができないという (大きな) 問題があります。以下の動作テスト済みの例。これは、VHDL (およびおそらく私が使用していない SV) では、はるかに簡単で明確になります。この種のことをたくさんやろうとしていて、始めたばかりの場合は、言語を変更する必要があります。

以下の 3x3 正方行列乗算のハードウェアは高速ですが、多くのハードウェアが犠牲になります。9 つの MAC ユニットを生成し、それぞれに 3 つの乗算器と 2 つの加算器が必要です。ビット幅について考える必要があります。このままのコードは、MAC の結果を 18 ビット値に割り当てますが、これは一般には機能しません ( と の値AB小さいため、コードは正しくシミュレートされます)。

リソースとタイミングについて考える必要があります。27 個の乗数と 18 個の加算器を持っていないが、急いで答えが必要ない場合は、それらを共有してください。制限内では、多くのサイクルと複雑な制御を犠牲にして、非常にコンパクトなシリアル ハードウェアを構築できます。

module top;

   wire[17:0]A[1:3][1:3];    // the matrices
   wire[17:0]B[1:3][1:3];
   wire[17:0]C[1:3][1:3];

   wire[(9*18)-1:0] Abits;   // bit-decomposed versions of the above
   wire[(9*18)-1:0] Bbits;
   wire[(9*18)-1:0] Cbits;

   genvar i,j;

   // set A and B with initial values
   generate 
      for(i=0; i<3; i=i+1)
         for(j=0; j<3; j=j+1) begin
            assign A[i+1][j+1] = i*3 + j;
            assign B[i+1][j+1] = i*3 + j + 1;
         end
   endgenerate

   // decompose A and B, set C
   generate 
      for(i=1; i<=3; i=i+1)
         for(j=1; j<=3; j=j+1) begin
            assign Abits[(((i-1)*3 + (j-1)) * 18)+17 -:18] = A[i][j];
            assign Bbits[(((i-1)*3 + (j-1)) * 18)+17 -:18] = B[i][j];
            assign C[i][j] = Cbits[(((i-1)*3 + (j-1)) * 18)+17 -:18];
         end
   endgenerate

   initial
      #1 $display("%4d %4d %4d\n%4d %4d %4d\n%4d %4d %4d\n",
                  C[1][1], C[1][2],C[1][3],
                  C[2][1], C[2][2],C[2][3],
                  C[3][1], C[3][2],C[3][3]);

   mmult3x3 U1(Abits, Bbits, Cbits);
endmodule

module mmult3x3
   (input  wire[(9*18)-1:0] AI,
    input  wire[(9*18)-1:0] BI,
    output wire[(9*18)-1:0] CO);

   wire[17:0]A[1:3][1:3];
   wire[17:0]B[1:3][1:3];
   wire[17:0]C[1:3][1:3];

   genvar i,j;

   generate 
      for(i=1; i<=3; i=i+1)
         for(j=1; j<=3; j=j+1) begin
            assign A[i][j] = AI[(((i-1)*3 + (j-1)) * 18)+17 -:18];
            assign B[i][j] = BI[(((i-1)*3 + (j-1)) * 18)+17 -:18];
            assign CO[(((i-1)*3 + (j-1)) * 18)+17 -:18] = C[i][j];
         end
   endgenerate

   // this is the bit that matters - everything else just works around shortcomings 
   // in the language:
   generate 
      for(i=1; i<=3; i=i+1)
         for(j=1; j<=3; j=j+1)
            assign C[i][j] = A[i][1]*B[1][j] + A[i][2]*B[2][j] + A[i][3]*B[3][j];
   endgenerate
endmodule
于 2013-10-04T12:06:27.920 に答える