0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Shrike-LiteでAtCoder問題を解く(5) 準備編⑤:公式サンプルからSPI Slave機能を取り込み、AtCoder実装テンプレートを作る

0
Last updated at Posted at 2026-07-11

はじめに

前回は、Shrike-Liteの回路図を確認し、RP2040からFPGAへ1bitのON/OFF状態を渡しました。

RP2040側のGPIOをON/OFFすると、その信号が基板上の配線を通ってFPGAへ入り、FPGA側LEDにも反映されるところまで確認しました。

今回は、Shrike公式GitHubリポジトリに公開されている spi_loopback_led サンプルを利用して、RP2040とFPGAの間でSPI通信を行います。

ただし、公式サンプルをそのまま動かして終わりにはしません。

今回の目的は、次の二つです。

  1. 公式サンプルに含まれるSPI Slave用Verilogモジュールを、自分のForgeFPGAプロジェクトへ取り込んで再利用する
  2. 再利用する共通部分と、問題ごとに変更する部分を整理し、今後のAtCoder実装に使えるテンプレートを作る

SPI通信を一からVerilogで実装するのはかなり大変です。

しかし、公式サンプルの中に使えそうなSPI Slaveモジュールがあれば、その部分を共通部品として利用し、受信後の処理だけを問題ごとに書き換えることができます。

今回は、FPGAが受信した1byteに1を加えてRP2040に返す簡単な処理を例として実装します。そのうえで、FPGA側とMicroPython側を共通部分と問題ごとに変更する部分に分け、atcoder_spi_template として整理します。

今回やること

今回の流れは以下です。

今回作る回路では、RP2040から受信した1byteにFPGA側で1を加え、その結果を次のSPI通信でRP2040へ返します。

FPGA側のLED制御は行いません。

RP2040から1byte送信
↓
公式サンプル由来のSPI Slaveモジュールで受信
↓
main.vの問題ごとに変更する部分に、動作確認用として受信値に1を加える
↓
次のSPI通信で加算結果をRP2040へ返す
↓
共通部分と問題ごとに変更する部分をテンプレートとして整理

公式spi_loopback_ledサンプル

今回利用するのは、Shrike公式GitHubリポジトリの以下のサンプルです。

examples/spi_loopback_led

主なファイル構成は次のようになっています。

spi_loopback_led
├── bitstream
│   └── spi_loopback_led.bin
├── ffpga
│   └── src
│       ├── spi_target.v
│       └── top.v
├── firmware
│   └── micropython
│       └── spi_loopback_led.py
└── spi_loopback_led.ffpga

このサンプルでは、RP2040がSPI Master、FPGAがSPI Slaveとして動きます。

公式コードではSPI Slave側を Target と表現しているため、Verilogモジュール名も spi_target になっています。

サンプルの動作は以下のようになっています。

RP2040から0xABを送信
→ FPGA側LEDを点灯

RP2040から0xFFを送信
→ FPGA側LEDを消灯

受信した1byte
→ 次のSPI通信でRP2040へ返す

外部のジャンパ線やLEDは必要ありません。

Shrike-Lite上のRP2040、FPGA、FPGA側LEDだけで動作を確認できる構成になっています。

サンプルを二つの部分に分けて見る

このサンプルのFPGA側は、二つのVerilogファイルで構成されています。

spi_target.v
top.v

それぞれは次のような役割を担っているようです。

ファイル 役割
spi_target.v SPI信号を処理して1byteを送受信する
top.v 受信したデータを元にLEDのON/OFF制御とSPIループバックデータをセットする

spi_target.v は、SCK、CS、MOSI、MISOといったSPI信号を扱います。

一方、top.vspi_target.v から受け取ったデータを使い、サンプル固有の処理を行っています。

今回再利用するのは、通信処理を担当する spi_target.v です。

公式サンプル固有のLED制御はコピーせず、AtCoder実装テンプレート用の main.v を新たに作成します。

spi_target.vの入出力

spi_target.v の主な入出力を整理すると、次のようになります。

SPIピン側

信号 方向 役割
i_ss_n 入力 CS信号
i_sck 入力 SPIクロック
i_mosi 入力 RP2040から受信する1bit信号
o_miso 出力 RP2040へ返す1bit信号
o_miso_oe 出力 MISO出力の有効化

自分のロジック側

信号 方向 役割
o_rx_data 出力 SPIで受信したデータ
o_rx_data_valid 出力 1byteの受信完了を示すパルス
i_tx_data 入力 次のSPI通信で返すデータ
o_tx_data_hold 出力 送信データを取り込むタイミング

SPIのシリアル信号を、自分の回路で扱いやすい1byteのデータへ変換してくれるわけです。

自分の main.v 側では、主に次の3本を見れば処理を作れます。

o_rx_data
o_rx_data_valid
i_tx_data

これなら、SCKのエッジやbit数を自分で数える処理を、問題ごとに書き直す必要はありません。

新しいForgeFPGAプロジェクトを作る

今回は、公式の spi_loopback_led.ffpga を直接変更せず、新しいプロジェクトを作成します。

プロジェクト名は、次のようにします。

atcoder_spi_template

ForgeFPGA Workshopでの新規プロジェクト作成手順は、前回の記事で確認したものと同じです。

使用するデバイスは、Shrike-Liteに搭載されている以下を選びます。

SLG47910V (Rev BB)

Project settings画面では以下のように値をセットします。

Shrike-LiteでAtCoder問題を解く(5)_001.png

新しいプロジェクトを作成したら、Verilogファイルを置くフォルダを確認します。

atcoder_spi_template
└── ffpga
    └── src
        └── main.v

spi_target.vを自分のプロジェクトへ取り込む

公式サンプルに含まれる次のファイルを、自分のプロジェクトへ取り込みます。

examples/spi_loopback_led/ffpga/src/spi_target.v

ただし、Windowsのエクスプローラーなどを使って .v ファイルをプロジェクトフォルダへコピーしただけでは、ForgeFPGA Workshop上でプロジェクトのソースファイルとして認識されないようです。

そこで、ForgeFPGA Workshop上から新しいVerilogファイルを作成し、公式サンプルの内容をコピーします。

まず、画面上部のツールバー"New Custom Module"ボタンをクリックするか、ForgeFPGA WorkshopのFileメニューから New Custom Module を選びます。

Shrike-LiteでAtCoder問題を解く(5)_002.png

モジュール登録ウィンドウが表示されますので、spi_target を入力してCreateです。

Shrike-LiteでAtCoder問題を解く(5)_003.png

ForgeFPGA Workshop上に空の spi_target.v が作成されたら、画面左側の Sources ツリーからspi_target.vファイルをダブルクリックして開きます。

公式サンプルの spi_target.v の内容をすべてコピーし、先ほどオープンした spi_target.v へ貼り付けて保存します。

これで、公式サンプルのSPI Slaveモジュールが、自分のプロジェクトのVerilogソースとして登録されます。

Shrike-LiteでAtCoder問題を解く(5)_004.png

この時点のファイル構成は次のようになります。

atcoder_spi_template
└── ffpga
    └── src
        ├── spi_target.v
        └── main.v

spi_target.v が公式サンプルから取り込んだ共通の通信部品、main.v が問題ごとの処理を記述するファイルです。

ライセンスについて

公式サンプルのコードを自分のプロジェクトへ取り込むため、ライセンスも確認しておきます。

Shrike公式リポジトリでは、ソフトウェアはGNU General Public License v2.0(GPL-2.0)で公開されています。

一方、HDL/RTL、回路図、PCBファイル、制約ファイルなどのハードウェア設計は、CERN Open Hardware Licence v1.2で公開されています。

今回取り込む spi_target.v はVerilogで記述されたHDLなので、利用や再配布を行う際には、公式リポジトリの LICENSE_HW.md も確認する必要があります。

本記事では学習目的で公式サンプルを利用していますが、自分のプロジェクトを公開・配布する場合は、使用したファイルに適用されるライセンス条件を確認してください。

テンプレート用のmain.vを書く

今回の main.v では、動作確認用として次の処理を行います。

1byteを受信する
↓
受信値に1を加える
↓
加算結果を返送用レジスタへ保存する

FPGA側のLED制御は行いません。

今後テンプレートを別のAtCoder問題へ使うときに迷わないよう、コード内で共通部分と問題ごとに変更する部分を分けておきます。

以下のコードをForgeFPGA Workshopで main.v に貼り付けてください。

(* top *) module main (
    // ===== 共通部分:Shrike-LiteとSPIの外部端子 =====
    (* iopad_external_pin, clkbuf_inhibit *) input clk,
    (* iopad_external_pin *) output clk_en,
    (* iopad_external_pin *) input rst_n,

    (* iopad_external_pin *) input  spi_ss_n,
    (* iopad_external_pin *) input  spi_sck,
    (* iopad_external_pin *) input  spi_mosi,
    (* iopad_external_pin *) output spi_miso,
    (* iopad_external_pin *) output spi_miso_en
);

    // ===== 共通部分:内部クロックとSPI送受信データ =====
    assign clk_en = 1'b1;

    wire [7:0] rx_data;
    wire       rx_data_valid;
    reg  [7:0] tx_data;

    // ===== 問題ごとに変更する部分 =====
    // 今回は動作確認用として、受信値に1を加えて返す。
    // AtCoder問題を実装するときは、この処理を問題ごとの判定・演算へ置き換える。
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            tx_data <= 8'h00;
        end else if (rx_data_valid) begin
            tx_data <= rx_data + 8'd1;
        end
    end

    // ===== 共通部分:公式サンプルから取り込んだSPI Slaveモジュール設定と接続 =====
    spi_target #(
        .CPOL(1'b0),
        .CPHA(1'b0),
        .WIDTH(8),
        .LSB(1'b0)
    ) u_spi_target (
        .i_clk(clk),
        .i_rst_n(rst_n),
        .i_enable(1'b1),

        .i_ss_n(spi_ss_n),
        .i_sck(spi_sck),
        .i_mosi(spi_mosi),
        .o_miso(spi_miso),
        .o_miso_oe(spi_miso_en),

        .o_rx_data(rx_data),
        .o_rx_data_valid(rx_data_valid),

        .i_tx_data(tx_data),
        .o_tx_data_hold()
    );

endmodule

今回、問題ごとに変更する部分には、動作確認用として次の処理を書きます。

tx_data <= rx_data + 8'd1;

例えば 0x12 を受信すると、0x13 を返送用レジスタへ保存します。

0x12を受信
↓
FPGA側で1を加える
↓
0x13を返送用レジスタへ保存

tx_data は8bitなので、0xFF に1を加えると桁あふれして 0x00 になります。

SPI通信の低レベル処理は、共通部分として取り込んだ spi_target.v が担当します。

IO Plannerでピン割り当てする

次に、IO PlannerでVerilog上の信号とFPGA側のピンを対応させます。

今回は、公式 spi_loopback_led サンプルと同じピン割り当てを使います。

FPGA側 Verilog上の信号
GPIO4_IN (Input) spi_ss_n
GPIO3_IN (Input) spi_sck
GPIO5_IN (Input) spi_mosi
GPIO6_OE (Output) spi_miso_en
GPIO6_OUT (Output) spi_miso
GPIO18_IN (Input) rst_n
OSC_EN (Output) clk_en
OSC_CLK (Input) clk

Shrike-LiteでAtCoder問題を解く(5)_005.png

公式サンプルのプロジェクトをForgeFPGA Workshopで開き、IO Plannerの設定を見比べながら設定すると分かりやすいです。

このピン割り当ても、今後のAtCoder実装で共通して使う部分です。

合成してbitstreamを生成する

main.vspi_target.v をプロジェクトへ追加し、IO Plannerの設定が終わったら、合成とbitstream生成を行います。

操作は第3回、第4回と同じです。

Synthesize
↓
Generate Bitstream

エラーがなくbitstreamを生成できたら、次のファイルを確認します。

atcoder_spi_template/ffpga/build/bitstream/FPGA_bitstream_MCU.bin

分かりやすいように、次の名前へ変更します。

atcoder_spi_template.bin

atcoder_spi_template.bin をShrike-LiteのUSBドライブへコピーします。

Shrike-LiteでAtCoder問題を解く(5)_006.png

RP2040側のテストコードを作る

次に、RP2040からSPI通信を行うMicroPythonコードを作ります。

ファイル名は次のようにします。

atcoder_spi_template_test.py

こちらも、今後問題を変更するときに使いやすいよう、共通部分と問題ごとに変更する部分をコメントで分けておきます。

コードは以下です。

from machine import Pin, SPI
import time
import shrike

# ===== 共通部分:bitstream名とShrike-Liteのピン設定 =====
BITSTREAM = "atcoder_spi_template.bin"

SCK = 2
CS = 1
MOSI = 3
MISO = 0
FPGA_RESET = 14

# ===== 共通部分:FPGAへのbitstream書き込みとリセット =====
shrike.reset()
shrike.flash(BITSTREAM)

reset_pin = Pin(FPGA_RESET, Pin.OUT, value=1)
reset_pin.value(0)
time.sleep_ms(100)
reset_pin.value(1)
time.sleep_ms(100)

# ===== 共通部分:SPI Masterの初期化 =====
cs = Pin(CS, Pin.OUT, value=1)

spi = SPI(
    0,
    baudrate=1_000_000,
    polarity=0,
    phase=0,
    bits=8,
    firstbit=SPI.MSB,
    sck=Pin(SCK),
    mosi=Pin(MOSI),
    miso=Pin(MISO)
)


# ===== 共通部分:1byteのSPI送受信 =====
def spi_exchange(value):
    tx = bytes([value])
    rx = bytearray(1)

    cs.value(0)
    spi.write_readinto(tx, rx)
    cs.value(1)

    return rx[0]


# ===== 問題ごとに変更する部分:入力データと期待値の確認 =====
# 今回は「受信値に1を加えて次回返す」回路をテストする。
patterns = [0x00, 0x12, 0x7F, 0xFF]
expected_rx = 0x00

for value in patterns:
    received = spi_exchange(value)

    result = "PASS" if received == expected_rx else "FAIL"

    print(
        "TX=0x{:02X} RX=0x{:02X} EXPECT=0x{:02X} {}".format(
            value,
            received,
            expected_rx,
            result
        )
    )

    # 今回の期待値計算
    expected_rx = (value + 1) & 0xFF
    time.sleep_ms(100)

# 動作確認用の後処理:最後に送った0xFFの処理結果を読み出す
received = spi_exchange(0x00)
result = "PASS" if received == expected_rx else "FAIL"

print(
    "TX=0x00 RX=0x{:02X} EXPECT=0x{:02X} {}".format(
        received,
        expected_rx,
        result
    )
)

SPI0は次の設定で使っています。

項目 設定
通信速度 1MHz
polarity 0
phase 0
データ長 8bit
bit順 MSB first

polarity=0phase=0 なのでSPI Mode 0です。

1byteを送受信する

spi_exchange() では、RP2040からFPGAへ1byteを送りながら、FPGAから返される1byteを受け取ります。

def spi_exchange(value):
    tx = bytes([value])
    rx = bytearray(1)

    cs.value(0)
    spi.write_readinto(tx, rx)
    cs.value(1)

    return rx[0]

CSをLowにしてFPGAを選択し、write_readinto() で送信と受信を同時に行います。

1byteの転送が終わったら、CSをHighに戻します。

この関数は、今後のAtCoder実装でも共通部分として利用します。

返ってくるのは一つ前の受信データを処理した結果

今回のFPGA回路では、1byteを受信したあとで1を加え、その結果を返送用レジスタへ保存します。

if (rx_data_valid) begin
    tx_data <= rx_data + 8'd1;
end

SPIでは送信と受信が同時に進むため、その通信で受信している値を処理し、同じ通信の途中で返すことはできません。

そのため、FPGAから返ってくるのは、一つ前のSPI通信で受信した値に1を加えた結果です。

1回目
RP2040から0x00を送信
FPGAから初期値0x00を受信

2回目
RP2040から0x12を送信
FPGAから前回の0x00に1を加えた0x01を受信

3回目
RP2040から0x7Fを送信
FPGAから前回の0x12に1を加えた0x13を受信

4回目
RP2040から0xFFを送信
FPGAから前回の0x7Fに1を加えた0x80を受信

5回目
RP2040から0x00を送信
FPGAから前回の0xFFに1を加えた0x00を受信

最後の 0xFF + 1 = 0x00 は、8bit演算の桁あふれによるものです。

これは不具合ではなく、今回の返送ロジックとSPIの全二重通信による動作です。

今後FPGAへ処理を依頼して結果を受け取る場合にも、基本的には次の形を使います。

コマンドやデータを送る
↓
FPGAが処理する
↓
次のSPI通信で結果を受け取る

Thonnyのシェルで実行して確認する

Shrike-LiteをPCへ接続し、ThonnyからRP2040上のMicroPythonへ接続します。

FPGA用の atcoder_spi_template.bin と、RP2040側の atcoder_spi_template_test.py をShrike-Liteへ保存しておきます。

そのあと、RP2040に接続されているThonnyのシェルから次のコマンドを実行します。

exec(open("atcoder_spi_template_test.py").read())

正常に動作すれば、Thonnyのシェルに次のようなログが表示されます。

TX=0x00 RX=0x00 EXPECT=0x00 PASS
TX=0x12 RX=0x01 EXPECT=0x01 PASS
TX=0x7F RX=0x13 EXPECT=0x13 PASS
TX=0xFF RX=0x80 EXPECT=0x80 PASS
TX=0x00 RX=0x00 EXPECT=0x00 PASS

Shrike-LiteでAtCoder問題を解く(5)_007.png

1回目の受信値は、リセット時に設定した返送用レジスタの初期値 0x00 です。

2回目以降は、一つ前に送った値にFPGA側で1を加えた結果が返っています。

0x00 → 0x01
0x12 → 0x13
0x7F → 0x80
0xFF → 0x00

RP2040から送ったデータにFPGA側の動作確認用処理を適用し、その結果をRP2040へ返すことができました。

公式サンプルから取り込んだもの

今回、公式サンプルから利用したのは、主に次の部分です。

spi_target.v
SPI信号のピン割り当て
RP2040側のSPI設定

今回の動作確認用に作成したのは、次の部分です。

受信データに1を加える処理
FPGAから返すデータの決め方
テストパターンと期待値の計算

整理すると、次のような役割分担になります。

公式サンプルから、必要な部分を取り出して共通部品として整理すれば、複雑な機能をすべて一から作らなくても、自分の目的に合った回路を作り始めることができてお得ですね。

AtCoder実装テンプレートとして使う

今回作成したプロジェクトは、今後のAtCoder実装の出発点として使います。

テンプレートのフォルダ構成は、次のように整理します。

atcoder_spi_template
├── bitstream
│   └── atcoder_spi_template.bin
├── ffpga
│   └── src
│       ├── spi_target.v
│       └── main.v
├── firmware
│   └── micropython
│       └── atcoder_spi_template_test.py
└── atcoder_spi_template.ffpga

ForgeFPGA Workshopが生成する作業用ファイルとは別に、再利用したいソース、bitstream、MicroPythonコードを分かりやすい位置へまとめておきます。

今後AtCoder問題をShrike-Liteへ実装するときは、このフォルダをコピーし、問題名に合わせてプロジェクトを作ります。

共通部分と問題ごとに変更する部分は、次のように整理できます。

対象 共通部分 問題ごとに変更する部分
spi_target.v 公式サンプル由来のSPI Slave処理 原則として変更しない
main.v 外部端子、SPI信号、spi_target の接続 受信データの保存方法、コマンド処理、判定・演算、返送データ
IO Planner RP2040とFPGAをつなぐSPI・リセット・クロックのピン割り当て 原則として変更しない
bitstream 生成・リネーム・Shrike-Liteへのコピー手順 問題ごとの main.v から再生成する
MicroPythonの初期化部 bitstream書き込み、FPGAリセット、SPI初期化、spi_exchange() 必要に応じて通信速度や転送単位を変更する
MicroPythonのテスト部 PASS/FAIL表示の基本形 入力データ、コマンド列、期待値、結果の読み出し手順

実際のAtCoder問題では、今回の加算処理を、問題ごとの判定回路や演算回路へ置き換えることにします。

例えば、全体の構成は次のようになります。

RP2040側
問題の入力を整形する
↓
SPIでコマンドとデータを送る
↓
spi_target.v
1byteずつ受信する
↓
main.vの問題ごとに変更する部分
判定や演算を行う
↓
返送用データを準備する
↓
spi_target.v
MISOで結果を返す
↓
RP2040側
結果を表示して期待値と比較する

SPI通信部分はテンプレートの共通部品として使い、問題ごとに変更するのは、その上に載せる処理とテスト内容です。

これなら、AtCoder問題を一つ実装するたびにSPI Slave回路やRP2040側の初期化処理を作り直す必要はありません。

前回の1bit通信との違い

前回と今回の違いをまとめると、次のようになります。

項目 前回 今回
通信方法 GPIO線1本 SPI
送信単位 ON/OFFの1bit 1byte
通信方向 RP2040からFPGA RP2040とFPGAの双方向
FPGA側の処理 入力をLEDへそのまま出力 受信完了を検出してデータを処理
実装方法 接続線を調べて自力実装 公式サンプルのモジュールを再利用
再利用方法 実験ごとの個別実装 共通部分と問題ごとに変更する部分を分けてテンプレート化
確認方法 2個のLED Thonnyのシェル上の送受信ログ

前回は、RP2040とFPGAの間にある信号線を確認し、1bitの状態を直接渡しました。

今回は、公式サンプルのSPI Slaveモジュールを取り込み、受信した1byteに1を加えて、その結果をRP2040へ返しました。

さらに、共通して利用する部分と問題ごとに変更する部分を整理し、次回以降のAtCoder実装に使える形へまとめました。

今回のまとめ

今回は、公式の spi_loopback_led サンプルから spi_target.v を取り出し、自分で作成した atcoder_spi_template プロジェクトへ組み込みました。

SPIの受信処理、送信処理、SCKやCSの扱いは spi_target.v に任せ、main.v では動作確認用として受信値に1を加える処理だけを書きました。

公式サンプルからSPI Slave機能を取り込む
↓
共通部品としてmain.vから呼び出す
↓
受信データを問題ごとに変更する処理へ渡す
↓
処理結果をRP2040へ返す
↓
FPGA側とMicroPython側をテンプレートとして整理する

公式サンプルに含まれる便利な部品を、自分のコードへ取り込んで使えることを確認できました。

また、main.vatcoder_spi_template_test.py に共通部分と問題ごとに変更する部分を明示し、フォルダ構成と役割分担も整理しました。

これで、Shrike-Lite上のRP2040からFPGAへデータを渡し、FPGA側で処理し、結果をRP2040へ返すためのAtCoder実装テンプレートが完成しました。

準備編のまとめ

これで、準備編として予定していた5回が終わりました。

確認したこと
準備編① Shrike-Liteの概要と開発環境
準備編② RP2040側のMicroPython開発ループ
準備編③ FPGA側のVerilog開発ループ
準備編④ GPIOによる1bit信号の受け渡し
準備編⑤ 公式SPI Slave機能の再利用とAtCoder実装テンプレートの作成

最初は、RP2040側とFPGA側で別々にLEDを点滅させました。

次に、回路図を確認して、RP2040からFPGAへ1bit信号を渡しました。

そして今回は、公式サンプルに含まれるSPI Slaveモジュールを自分のプロジェクトへ取り込み、受信した1byteに1を加えて返す処理を行いました。

さらに、FPGA側とMicroPython側を共通部分と問題ごとに変更する部分に分け、今後のAtCoder実装に再利用できるテンプレートとして整理しました。

これで、Shrike-Lite上のRP2040とFPGAを組み合わせて、AtCoder問題の処理を試すための準備が整いました。

次回

次回からは、今回完成した atcoder_spi_template を使い、AtCoderの問題を実際にShrike-Liteへ実装してみます。

問題ごとに考える必要があるのは、主に次の部分です。

  • 問題の入力をどのようなデータとしてFPGAへ渡すか
  • RP2040とFPGAをどう役割分担するか
  • FPGA側でどのような判定や演算を行うか
  • 結果をどのような形式で返すか
  • どのようにテストするか

SPI通信部分には、今回取り込んだ spi_target.v と、テンプレートに整理した共通処理を利用できます。

普通にプログラムを書けば簡単に解ける問題を、あえてRP2040とFPGAへ分けて実装するとどうなるのか。

いよいよ次回から試してみます。

前回:準備編④:回路図を見てRP2040からFPGAへ1bit信号を渡す

次回:Shrike-LiteでAtCoder問題を解く(6):ABC456A - Dice

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?