KR260でデジタル信号処理してみた! (1)
皆さん、こんにちは。新人エンジニアのノリさんです!今回はKR260を用いたデジタル信号処理のハードウェアデザインの一部を作成していきます。
https://www.hackster.io/whitney-knitter/dsp-for-soms-getting-started-with-dds-fir-compiler-ips-947cb4を参考に、デジタルフィルタの動作を確認するまでの作業を行います。
最終的な目標である、デジタルフィルタをKR260で動かすことは、次回行う予定です。
2024-1-4
デジタルフィルタについて補足
デジタルフィルタは離散化された音声、画像、電気パルスなどのデジタル信号から雑音を除去し、所望の信号のみを得るためのシステムです。
雑音が高周波である場合、ローパスフィルタを用いて信号の高周波成分を除去することで、雑音の除去を実現できます。
バンドパスフィルタであれば特定の帯域以外の周波数成分を除去し、ハイパスフィルタであれば低周波成分を除去することができます。
Step0:ハードウェア要件
- KR260 Robotics Starter Kit (/japan/products/product-highlights/xilinx-kr260)
- KR260用電源(KR260 Robotics Starter Kit に付属)
- USB-A to micro-B ケーブル(KR260 Robotics Starter Kit に付属)
- マイクロSDカード(最低16GB、KR260 Robotics Starter Kit に付属しているものでOK)
Step1: ハードウェアデザインの作成
ここでは、信号処理をするためのハードウェアデザインを作っていきます
Vivadoを開きます、今回はVer. 2022.1を用います
- $ source /tools/Xilinx/Vivado/2022.1/settings64.sh
- $ vivado
Create Project → Next → プロジェクト名をKR260DSPにしてNext → Next→ BourdタブからKR260を選択して、Connectionsを開いて次のように設定します
Nextを押して下の図と同じ設定になっていることを確認し、Finishをクリックします
画面左にあるFlow NavigatorからCreate Block Designを開いてOKをクリックし、ブロックデザインを作成します
Diagramウィンドウの上部にある+ボタンをクリックし、表示されたウィンドウで「zynq」と検索して、リスト内のZynq UltraScale+ MPSoCをダブルクリックして、IPブロックをデザインに追加します
Run Block Automationをクリックし、表示されたウィンドウの「Apply Board Preset」にチェックが入っていることを確認し、OKをクリックします
Block Automationが完了したら、+ボタンからProcessor System Resetを追加して、K26 のプログラマブル ロジック (PL) を実行するロジックへのリセット信号のタイミングを制御します
Run Connection Automationをクリックし、表示されたウィンドウの「All Automaton」にチェックを入れて、OKをクリックします
Zynq UltraScale+ MPSoC 上のpl_clk0とmaxihpm0_fpd_aclk、pl_clk1とmaxihpm1_fpd_aclkを接続します
下の図のようになっていることを確認します
Sourceウィンドウからブロックデザインファイルを右クリックし、 Create HDL Wrapperを選択して、表示されたウィンドウでOKをクリックします
次に、信号を生成するためのDDS Compilerをデザインに追加します
今回は1MHzから10MHzまで1MHz間隔で変化するチャープ信号を生成します
(何故そのようにするかはhttps://www.hackster.io/whitney-knitter/dsp-for-soms-getting-started-with-dds-fir-compiler-ips-947cb4#toc-chirp-signal-with-dds-compiler-3を参照)
Diagramウィンドウの上部にある+ボタンをクリックし、表示されたウィンドウから「dds」と検索し、リスト内の DDS Compilerをダブルクリックしてブロック デザインに追加します
DDS Compiler IPをダブルクリックしてその構成ウィンドウを開きます
Configurationタブから、Parameter Selectionを「Hardware Parameters」に設定し、「Phase width」を32、「Output Width」を16に設定します
Implementationタブから、Phase Increment Programmabilityを「Streaming」に設定し、Phase Offset ProgrammabilityをNoneのままにします
OutputSelection を「Sine and Cosine」ではなく、「Sine」または「Cosine」に設定します
Detailed Implementationタブから、DATA Has TLASTを「Packet Framing」に設定し、「Output TREADY」チェックボックスをオンにします
「ARESETn」のオプションをチェックして、DDS Compilerにリセットポートを作成します
Summaryタブから反映した設定を確認します
作成したDDS Compilerをクリックしてctrl+cでコピーし、Diagramウィンドウの空白部分をクリックしてctrl+pでペーストします
DDS Compilerを再度コピー&ペーストし、下の図と同じ状態にします
位相増分用のモジュールを追加するためのVerilogコードを作成します
次のVerilogコードをphase_inc_sm.vとして任意の場所に保存します
`timescale 1ns / 1ps module phase_inc_sm( input clk, input reset, output reg m_axis_phase_tvalid, output reg m_axis_phase_tlast, input m_axis_phase_tready, output reg [31:0] m_axis_phase_tdata ); reg [31:0] carrier_freq; reg [31:0] carrier_period; // 100 kHz parameter carrier_freq_100k = 32'h418938; parameter carrier_period_100k = 32'd1000; parameter carrier_freq_incr_100k = 32'h418937; // 1 MHz parameter carrier_freq_1m = 32'h28F5C29; parameter carrier_period_1m = 32'd100; // 10 MHz parameter carrier_freq_10m = 32'h19999990; // 50 MHz - DO NOT USE parameter carrier_freq_50m = 32'h80000000; parameter carrier_period_100ms = 32'd10000000; reg [2:0] state_reg; reg [31:0] period_wait_cnt; reg [3:0] cycle_cnt; parameter init = 3'd0; parameter SetCarrierFreq = 3'd1; parameter SetTvalidHigh = 3'd2; parameter SetSlavePhaseValue = 3'd3; parameter CheckTready = 3'd4; parameter WaitState = 3'd5; parameter SetTlastHigh = 3'd6; parameter SetTlastLow = 3'd7; parameter default_tdata = 32'h0; always @ (posedge clk)// or posedge reset) begin // Default Outputs if (reset == 1'b0) begin m_axis_phase_tdata[31:0] <= default_tdata; cycle_cnt <= 4'd0; state_reg <= init; end else begin case(state_reg) init : //0 begin cycle_cnt <= 4'd0; period_wait_cnt <= 32'd0; m_axis_phase_tlast <= 1'b0; m_axis_phase_tvalid <= 1'b0; carrier_freq <= 32'h0; state_reg <= SetCarrierFreq;// WaitForStart; end SetCarrierFreq : //1 begin if (carrier_freq > carrier_freq_10m) begin carrier_freq <= carrier_freq_1m; end else begin carrier_freq <= carrier_freq + carrier_freq_1m; end carrier_period <= carrier_period_1m; state_reg <= SetTvalidHigh; end SetTvalidHigh : //2 begin m_axis_phase_tvalid <= 1'b1; //per PG141 - tvalid is set before tready goes high state_reg <= SetSlavePhaseValue; end SetSlavePhaseValue : //3 begin m_axis_phase_tdata[31:0] <= carrier_freq; state_reg <= CheckTready; end CheckTready : //4 begin if (m_axis_phase_tready == 1'b1) begin state_reg <= WaitState; end else begin state_reg <= CheckTready; end end WaitState : //5 begin if (period_wait_cnt >= carrier_period) begin period_wait_cnt <= 32'd0; state_reg <= SetTlastHigh; end else begin period_wait_cnt <= period_wait_cnt + 1; state_reg <= WaitState; end end SetTlastHigh : //6 begin m_axis_phase_tlast <= 1'b1; state_reg <= SetTlastLow; end SetTlastLow : //7 begin m_axis_phase_tlast <= 1'b0; state_reg <= SetCarrierFreq; end endcase end end endmodule
Flow NavigatorからAdd Sourcesを開き、Add or create design sourcesが選択されていることを確認してNextをクリックします
Add Filesから先程作成したphase_inc_sm.vを選択し、Finishをクリックします
Diagramウィンドウの空白スペースの任意の場所を右クリックし、メニューAdd ModulesからAdd Modulesを選択します
phase increment smを選択し、OKをクリックします
phase increment smを2回コピー&ペーストして、他の DDS Compilerごとに1つずつ追加します
dds_compiler_0~2のSM AXIS_PHASE0とphase_inc_sm_0~2のm_axis_phaseをそれぞれ接続します
Run Connection Automationをクリックし、表示されたウィンドウの「All Automaton」にチェックを入れて、OKをクリックします
Diagramウィンドウの上部にあるRegenerate Layoutボタンをクリックして、下の図のようになっていることを確認してください
次に、FIRフィルタのためのIPをデザインに追加します
FIRフィルタの出力は、フィルタ係数との重み付き移動平均、即ち積と和の形で表現されます
Diagramウィンドウの上部にある+ボタンをクリックし、表示されるウィンドウで「fir」を検索し、リスト内のFIR Compilerをダブルクリックしてブロック デザインに追加します
FIR Compiler IP ブロックをダブルクリックして、構成ウィンドウを開きます
Channel Specificationタブの「Input Sampling Freqency」と「Clock Freqency」をそれぞれ100MHzに設定します
ImplementationタブのQuantizationを「Quantize Only」に、「Coefficient Fractional Bits」を2に変更します
OKをクリックしてFIRの構成ウィンドウを閉じ、FIR Compiler IPを2回コピー&ペーストします
dds_compiler_0~2のM_AXIS_DATAとfir_compiler_0~2のS_AXIS_DATAを接続し、fir_compiler_0~2のaclkをpl_clk0に接続します
Diagramウィンドウの上部にあるRegenerate Layoutボタンをクリックして、下の図のようになっていることを確認してください
次の3つの係数ファイルを任意の場所に保存します(lpf.coe, bpf.coe, hpf.coeはそれぞれ、ローパスフィルタ、バンドパスフィルタ、ハイパスフィルタのフィルタ係数です)
lpf.coe
Radix=10; CoefData= -255, -260, -312, -288, -144, 153, 616, 1233, 1963, 2739, 3474, 4081, 4481, 4620, 4481, 4081, 3474, 2739, 1963, 1233, 616, 153, -144, -288, -312, -260, -255
bpf.coe
Radix=10; CoefData= 132, -57, -61, -65, -60, -45, -24, -6, -8, -40, -106, -196, -285, -336, -310, -178, 68, 401, 766, 1080, 1251, 1202, 890, 328, -410, -1199, -1884, -2309, -2358, -1981, -1214, -175, 953, 1962, 2659, 2907, 2659, 1962, 953, -175, -1214, -1981, -2358, -2309, -1884, -1199, -410, 328, 890, 1202, 1251, 1080, 766, 401, 68, -178, -310, -336, -285, -196, -106, -40, -8, -6, -24, -45, -60, -65, -61, -57, 132
hpf.coe
Radix=10; CoefData= 109, 1, 12, -33, -140, -256, -298, -209, 2, 275, 517, 632, 550, 247, -222, -722, -1073, -1111, -761, -88, 716, 1382, 1662, 1415, 673, -358, -1351, -1972, -1987, -1360, -272, 934, 1865, 2214, 1865, 934, -272, -1360, -1987, -1972, -1351, -358, 673, 1415, 1662, 1382, 716, -88, -761, -1111, -1073, -722, -222, 247, 550, 632, 517, 275, 2, -209, -298, -256, -140, -33, 12, 1, 109
任意のFIR Compilerをダブルクリックして構成ウィンドウを開き、Filter OptionタブでCOEファイルを指定します
「Select Source」をCOE Fileに設定し、Coefficient Fileに保存したCOEファイルのいずれかを選択します
Freq. Response tabから結果を観察することができます
lpf.coeでの結果
bpf.coeでの結果
hpf.coeでの結果
感想
今回はKR260で信号処理を行うためのハードウェアデザインの一部の設計を行い、それを利用してフィルタの動作確認を行いました。
フィルタが理論通りの働きをしたことは大変うれしく感じました。
次回はハードウェアデザインの実装を進めてKR260上で動かしていく予定です(予定は変更されることもあります)。
それでは、また次回お会いしましょう!See you next time!

ブログ
AMDによる設計およびデバッグ手法のブログ、およびアヴネット社員によるAMD製品を用いた開発チャレンジのブログです。

Kria
Kria SOMはアダプティブSoCデバイスを搭載しており、スマートカメラやエンベデッドビジョンなどに最適です。
AMD製品に関連する技術ブログ
- エンジニアブログの再開およびテクニカルウェビナーのご案内
- 初心者のためのPython & Numpy入門
- KR260でIntel RealSenseを動かしてみた!
- Vitis HLSで足し算IPを作ってみた!(プログラミング編)
- KD240でモータ制御してみた!
- KR260でデジタル信号処理してみた! (3)
- KR260でデジタル信号処理してみた! (2)
- KR260でデジタル信号処理してみた! (1)
- KR260でロボットアームを動かしてみた! (2)
- KR260でロボットアームを動かしてみた! (1)
- KR260でROS2を使ってキャリブレーション&マーカー検出してみた!
- KR260とPynqでAIカメラを動かしてみた!
- KR260でROS2 Perception Stack Applicationを動かしてみた!【2】
- KR260でROS2 Perception Stack Applicationを動かしてみた!
- Kria SOMでTPM2.0を動かしてみた!
- VivadoでKR260のハードウェアデザインを作って動かしてみた!
- ROS2 Multi-Node Communications via TSNを動かしてみた!
- AIBOX-ReIDを動かしてみた!