« AXIバスを横から覗き見るVivadoのIPを作る | トップページ | ついに、Kintex-7で安定したHDMI 1080p出力に成功! »

2020.11.20

AXI Liteのコアを作り直したらビデオ出力が動いた!

もうね、激おこぷんぷん丸ですよ。

Video Out回路が動かない原因が、Vivadoが生成したステートマシンのフライングだったなんて・・。ツールが自動で生成したIPならちゃんと動くと思うでしょ!?

ここでグダグダいっても仕方がないので、正しいステートマシンの作り方を解説します。

ステートマシンってのは、中に「カウンタ」を入れるんです。ベースとなるカウンタを作って、そのカウンタがカウントアップする条件をAWREADYやBVALIDなどいろいろな信号に関連付けていくのです。

こういうとき、考え方を整理するため、AXI Liteの基本的な動かし方を図にしてみます。

Axilstate

冗長なステートもありますが、気にせずにいきましょう。

とりあえず、0~6まで数えられるカウンタを用意して、そのカウンタの値=ステートとします。カウンタの遷移はcase文で作ります。

WVALIDやAWVALIDなどの信号出力は、特定のステートでそれを出す(ステートマシン中に遷移する信号として記述する)か、ステートをデコードして出す(ステートマシンの外側で書く)ようにします。

これを実際のコードに落とし込みます。上のステートマシンをそのまま書くとあまりにも冗長なので少し縮めています

process(clk) begin
if(clk'event and clk='1') then
if(aresetn = '0') then
wstate <= 0;
windex <= 0;
awvalid <= '0';
wvalid <= '0';
bready <= '0';
else
case wstate is
when 0 =>
awvalid <= '0';
wvalid <= '0';
if(windex < 16) then
wstate <= wstate + 1;
end if;
when 1 =>
case windex is
when 0 =>
awaddr <= x"00000000";--MM2S_DMACR
wdata <= x"00000003";--MM2S_DMACR
when 1 =>
awaddr <= x"0000005c";--MM2S_START_ADDRESS1
wdata <= FRAME_ADDRESS_0;--x"00000000;--MM2S_START_ADDRESS1
when 2 =>
awaddr <= x"00000060";--MM2S_START_ADDRESS2
wdata <= FRAME_ADDRESS_1;--MM2S_START_ADDRESS2
・・・(中略)・・・
when others =>
awaddr <= x"0000FFFF";
wdata <= x"00000000";
end case;
awvalid <= '1';
wstate <= wstate + 1;
when 2 =>
if(awready = '1') then
awvalid <= '0';
wvalid <= '1';
wstate <= wstate + 1;
end if;
when 3 =>
if(wready = '1') then
wstate <= wstate + 1;
bready <= '1';
wvalid <= '0';
end if;
when 4 =>
if(bvalid = '1') then
wstate <= wstate + 1;
end if;
when 5 =>
windex <= windex + 1;
wstate <= 0;
when others =>
wstate <= 0;
end case;
end if;
end if;
end process;

シンプルでしょ?ちゃんと動きます。

Vivadoが生成した回路と違って、アドレス系のハンドシェイクとデータ系のハンドシェイクの順序ができているし、BVALIDをちゃんと待つようにもなっている。

あと、VHDLやVerilogでは、if文やcase文の中ではstate_next <= *** みたいな信号を作るだけにしておいて、別のprocess文でstate <= state_nextとする書き方もありますが、分かりにくくなるのでやめましょう。

「case文でstateを判断し、遷移条件を書いて次のstateを直接指定する」ようにしてください。2つに分けない。

 

波形を見ると、当たり前ですがハンドシェイクが効いています。AWVALID & AWREADYが来てからWVALIDを出し、WVALID & WREADYが来てBVALIDを待ってから次のデータを出すようになっています。

Viddebug9

AXI LiteでAXI Video DMAコアを設定したら、AXI MMが動き、AXI Streamが動くとう連携した動作も見えるようになりました。(ILAだと3つのILAコアが別々だから、こういうデバッグはやりにくいですよね。)

Viddebug10

Video DMAが動き出し、Streamが動き出し、無事にv_tcとaxis_vid_outもロックがかかるようになりました。

これでHDMI端子からメモリの中身の画像が出力されるようになりました。

 

|

« AXIバスを横から覗き見るVivadoのIPを作る | トップページ | ついに、Kintex-7で安定したHDMI 1080p出力に成功! »

コメント

このステートマシンだとAWREADYを待ってWVALIDを1にしているので、デッドロックが発生する可能性があります。
AXI4インターフェースのWrite側のステートマシンはAddress ChannelとData Channelで分けた方が良いと思います。
AMBA® AXI™ and ACE™ Protocol Specificationの44ページのCautionを見てください。
https://static.docs.arm.com/ihi0022/e/IHI0022E_amba_axi_and_ace_protocol_spec.pdf

投稿: marsee | 2020.11.21 04:16

そうなんですね。もう少し調べてみます。

投稿: なひたふ | 2020.11.21 09:57

コメントを書く



(ウェブ上には掲載しません)




« AXIバスを横から覗き見るVivadoのIPを作る | トップページ | ついに、Kintex-7で安定したHDMI 1080p出力に成功! »