Browsed by
Month: 2022年12月

[FPGA] ZedBoard で FPGA プログラミング大全をしたメモ

[FPGA] ZedBoard で FPGA プログラミング大全をしたメモ

ZedBoard で FPGA プログラミング大全を進めるための変更点。個人的なメモ用。間違っている可能性が大きいので注意。

Constrants (xdc)

set_property -dict { PACKAGE_PIN Y9   IOSTANDARD LVCMOS33 } [get_ports { CLK }];
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports CLK]

set_property -dict { PACKAGE_PIN P16    IOSTANDARD LVCMOS18 } [get_ports { RST }];

set_property -dict { PACKAGE_PIN AA19   IOSTANDARD LVCMOS33 } [get_ports { VGA_HS }];
set_property -dict { PACKAGE_PIN Y19    IOSTANDARD LVCMOS33 } [get_ports { VGA_VS }];

set_property -dict { PACKAGE_PIN Y21    IOSTANDARD LVCMOS33 } [get_ports { VGA_B[0] }];
set_property -dict { PACKAGE_PIN Y20    IOSTANDARD LVCMOS33 } [get_ports { VGA_B[1] }];
set_property -dict { PACKAGE_PIN AB20   IOSTANDARD LVCMOS33 } [get_ports { VGA_B[2] }];
set_property -dict { PACKAGE_PIN AB19   IOSTANDARD LVCMOS33 } [get_ports { VGA_B[3] }];

set_property -dict { PACKAGE_PIN AB22   IOSTANDARD LVCMOS33 } [get_ports { VGA_G[0] }];
set_property -dict { PACKAGE_PIN AA22   IOSTANDARD LVCMOS33 } [get_ports { VGA_G[1] }];
set_property -dict { PACKAGE_PIN AB21   IOSTANDARD LVCMOS33 } [get_ports { VGA_G[2] }];
set_property -dict { PACKAGE_PIN AA21   IOSTANDARD LVCMOS33 } [get_ports { VGA_G[3] }];

set_property -dict { PACKAGE_PIN V20    IOSTANDARD LVCMOS33 } [get_ports { VGA_R[0] }];
set_property -dict { PACKAGE_PIN U20    IOSTANDARD LVCMOS33 } [get_ports { VGA_R[1] }];
set_property -dict { PACKAGE_PIN V19    IOSTANDARD LVCMOS33 } [get_ports { VGA_R[2] }];
set_property -dict { PACKAGE_PIN V18    IOSTANDARD LVCMOS33 } [get_ports { VGA_R[3] }];

MMCME2_BASE

   MMCME2_BASE #(
      .BANDWIDTH("OPTIMIZED"),  // Jitter programming (OPTIMIZED, HIGH, LOW)
      .CLKFBOUT_MULT_F(18.0),   // 乗数M(2.000-64.000)
      .CLKFBOUT_PHASE(0.0),     // 位相(-360.000-360.000)
      .CLKIN1_PERIOD(5.0),      // CLKINの周期
      // CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128)
      .CLKOUT1_DIVIDE(1),
      .CLKOUT2_DIVIDE(1),
      .CLKOUT3_DIVIDE(1),
      .CLKOUT4_DIVIDE(1),
      .CLKOUT5_DIVIDE(1),
      .CLKOUT6_DIVIDE(1),
      .CLKOUT0_DIVIDE_F(35.75),  // 除数Q(1.000-128.000)
      // CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99).
      .CLKOUT0_DUTY_CYCLE(0.5), // デューティ比
      .CLKOUT1_DUTY_CYCLE(0.5),
      .CLKOUT2_DUTY_CYCLE(0.5),
      .CLKOUT3_DUTY_CYCLE(0.5),
      .CLKOUT4_DUTY_CYCLE(0.5),
      .CLKOUT5_DUTY_CYCLE(0.5),
      .CLKOUT6_DUTY_CYCLE(0.5),
      // CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000).
      .CLKOUT0_PHASE(0.0),
      .CLKOUT1_PHASE(0.0),
      .CLKOUT2_PHASE(0.0),
      .CLKOUT3_PHASE(0.0),
      .CLKOUT4_PHASE(0.0),
      .CLKOUT5_PHASE(0.0),
      .CLKOUT6_PHASE(0.0),
      .CLKOUT4_CASCADE("FALSE"), // Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE)
      .DIVCLK_DIVIDE(2),         // 除数D(1-106)
      .REF_JITTER1(0.0),         // Reference input jitter in UI (0.000-0.999).
      .STARTUP_WAIT("FALSE")     // Delays DONE until MMCM is locked (FALSE, TRUE)
   )

ZedBoard は 100MHz なので、書籍にのっていた数値をもとに、上のように変更した。

[FPGA] ZedBoard から VGA 出力

[FPGA] ZedBoard から VGA 出力

FPGA マガジンや、FPGA プログラミング大全に乗っていた、VGA 出力を ZedBoard で試してみる。

分周回路

reg [1:0] cnt;

always @( posedge clk, posedge reset ) begin
    if ( reset )
        cnt <= 2'h0;
    else
        cnt <= cnt + 2'h1;
end

assign pck = cnt[1];

Zedboard のクロックは 100MHz なので、これを4分周して 25MHz のクロックを作っている。cnt レジスタは 2bit で +1 でカウントアップをし続けることで、00 -> 01 -> 10 > 11 を繰り返す。この時、最上位 bit の cnt[1] が 1 になる立ち上がりを取得することで 1/4 のクロックが得られる?

ボードからの出力

FPGA からの出力はデジタル情報なので「ラダー抵抗」と呼ばれる仕組みを使って D-A 変換を行い、目的の電圧 (0.7V?) に変換してから VGA 端子で出力している。当たり前だが VGA はアナログなので、アナログに変換しないといけない。

参考

  • FPGA マガジン No.7
  • FPGA プログラミング大全 Xilinx編

Video Graphics Array
https://ja.wikipedia.org/wiki/Video_Graphics_Array
VGA端子
https://ja.wikipedia.org/wiki/VGA%E7%AB%AF%E5%AD%90
VGA Signal Timing
http://www.tinyvga.com/vga-timing
11 VGA Port
https://digilent.com/reference/programmable-logic/zybo/reference-manual
ちょっとTea Time!? VGAを調べてみる
http://www.easyaudiokit.com/bekkan2020/TeaTime8/vga.html
VGAモジュールの作成
http://www.arch.cs.kumamoto-u.ac.jp/~kuga/cad/exp/sys/2009/vga.html
分周器・CPUトップモジュール
https://sagara-works.jp/research-and-development/code-prescaler/

[DirectX12] World, View, Projection マトリックス

[DirectX12] World, View, Projection マトリックス

World 行列

View 行列

XMVECTOR Eye = XMVectorSet( 0.0f, 0.0f, -5.0f, 0.0f );
XMVECTOR At = XMVectorSet( 0.0f, 0.0f, 0.0f, 0.0f );
XMVECTOR Up = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f );
g_View = XMMatrixLookAtLH( Eye, At, Up );

カメラ位置(座標)と、カメラの見ている場所(注視点)、そしてカメラの上方向のベクトルをXMMatrixLookAtLH に指定することで View 行列が作られる。この行列によって、World 座標から定義した View 座標への変換が行える。

上記の Eye, At, Up から作られる View 行列はこちら。

{1.00, 0.00, 0.00, 0.00}
{0.00, 1.00, 0.00, 0.00}
{0.00, 0.00, 1.00, 0.00}
{0.00, 0.00, 5.00, 1.00} 

計算式は以下。

zaxis = normal(At - Eye)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)

 xaxis.x           yaxis.x           zaxis.x          0
 xaxis.y           yaxis.y           zaxis.y          0
 xaxis.z           yaxis.z           zaxis.z          0
-dot(xaxis, eye)  -dot(yaxis, eye)  -dot(zaxis, eye)  1
https://learn.microsoft.com/ja-jp/windows/win32/direct3d9/d3dxmatrixlookatlh

計算式を見れば分かるが up ベクトルが必要なのは、カメラからの視線のベクトルと up 方向のベクトルの外積を取って、横方向(xaxis)のベクトルを計算するために使用している。つまり、カメラの3次元での軸を決定するために、上方向がどちらかという情報が必要になる。

Projection 行列

g_Projection = XMMatrixPerspectiveFovLH( XM_PIDIV4, width / (FLOAT)height, 0.01f, 100.0f );
  • XM_PIDIV4 は 0.785398163f(3.14/4)
  • 2つ目はビュースペースのアスペクト比。(640/480=1.333333)
  • 3つ目と、4つ目は NearPlane と FarPlane。(0.01~100.0)

これによって、下記の Projection 行列が得られる。

{1.81066, 0.00, 0.00, 0.00}
{0.00, 2.41421, 0.00, 0.00}
{0.00, 0.00, 1.0001, 1.00}
{0.00, 0.00, -0.01, 0.00}

計算式としては下記。

xScale     0          0               0
0        yScale       0               0
0          0       zf/(zf-zn)         1
0          0       -zn*zf/(zf-zn)     0
where:
yScale = cot(fovY/2)

xScale = yScale / aspect ratio

https://learn.microsoft.com/ja-jp/windows/win32/direct3d9/d3dxmatrixperspectivefovlh

Viewport 行列

640×480 のレンダーターゲットに描画する場合は、Viewport も Width 640, Height 480 に設定する。他は通常はデフォルト値の X, Y 0で、Min 0.0, Max 1.0 になるのが普通。

    dwWidth/2,              0,             0, 0,
            0,    -dwHeight/2,             0, 0,
            0,              0, dwMaxZ-dwMinZ, 0,
dwX+DwWidth/2, dwHeight/2+dwY,        dwMinZ, 1,

https://learn.microsoft.com/ja-jp/windows/win32/direct3d9/viewports-and-clipping

実際は width, height ぐらいしかパラメータは設定しないので、

w = width / 2
h = height / 2

w  0 0 0
0 -h 0 0
0  0 1 0
w  h 0 1

ぐらいの単純な行列になる。

SV_Position の値

頂点シェーダーを使用して、上記のような View, Projection 行列で、ローカル座標 [ -1.0f, 1.0f, -1.0f] を変換した場合はこのような結果になる。

 [-1.81066, 2.41421, 3.9904, 4.00]

頂点シェーダーから SV_Position へ渡している値はこれ。
ラスタライザを通り、ピクセルシェーダーの入力として渡ってくる SV_Position は下記のようになる。

[175.50, 95.50, 0.9976, 4.00]

X, Y はピクセルのスクリーン座標。
Z は Depth Buffer に書かれる値と一致する。頂点シェーダーからの出力 3.9904 / 4.0 = 0.9976 になる。
W は頂点シェーダーでの World, View, Projection の計算結果がそのまま来る。

Reference

https://shikihuiku.github.io/post/projection_matrix/
Windows Sysinternals

Windows Sysinternals

Windows Sysinternals は、主に Windows マシンの管理者や開発者向けに提供される、ユーティリティーのアプリケーション。

ここから、個別にダウンロード可能
https://learn.microsoft.com/en-us/sysinternals/downloads/

ProcessExplorer

タスクマネージャーよりも詳細にプロセスの情報を見ることが出来る。プロセスごとの詳細な RAM 使用率など。また、 System.exe を選択すると、ここからロードされている .sys ファイルの詳細なども見ることが出来る。
https://learn.microsoft.com/en-us/sysinternals/downloads/process-explorer

DebugView

アプリケーションから標準出力に書き出されるメッセージを表示することが出来る。
https://learn.microsoft.com/en-us/sysinternals/downloads/debugview

Windowsのドライバー開発

Windowsのドライバー開発

ソフトウェアのインストール

ドライバー開発には、下記の3つが必要。

  • Visual Studio
  • Windows SDK
  • WDK (Windows Driver Kit)

使用する Windows のバージョンや、インストールする Visual Studio、Windows SDK/WDK は環境によって一致させておかないといけない。そうしないと WDK インストール時に、対応する SDK が見つからない旨の Warning が表示される。

私は Windows 10 22H2 に、Visual Studio 2019 をインストールして、Windows SDK 2004 と WDK for Windows10 2004 を導入した。正しくインストールされれば、Visual Studio を立ち上げたときの「新しいプロジェクト作成」で Driver 制作のプロジェクトが使用できる。

ドライバファイル

Windows ドライバーの構成ファイルは下記。

  • ドライバー情報ファイル (.inf)
  • カーネルモードドライバー (.sys)
  • ユーザーモードドライバー (.dll)

必ずしもこの3つがある訳では無いが、概ねこれらのファイルでドライバーは動いている。

Reference

Windows ハードウェア開発者向けドキュメント
https://learn.microsoft.com/ja-jp/windows-hardware/drivers/

Windows でドライバーの使用を開始する
https://learn.microsoft.com/ja-jp/windows-hardware/drivers/gettingstarted/

ドライバーの開発、テスト、および展開
https://learn.microsoft.com/ja-jp/windows-hardware/drivers/develop/