Verilog-HDL 両エッジ対応
両エッジ対応ですが使いどころがイメージしにくいと思いますが、例えばI2Sフォーマット(受信)のLR信号でデータのラッチをかけたい場合などに必要となります。
さて↓のタイミングチャートをご覧ください。
上記フォーマットでLRCK変化時にデータをラッチしてあわせて完了パルスを出力します。パルスのクリアにはBCKを使うことにします。これをコードにすると
always @ (lrck or negedge bck)
// 処理
という記述にで対応できますが、Model-Simでは問題ありませんが、Quartus IIではエラーとなります。
ダブルエッジとシングルエッジをorできないということのようです。
Webをいろいろと調べましたが、これといった解決法を見つけられませんでしたが、案外解決方法は簡単でしたのでここで紹介します。
↓のコードをご覧ください
//第1段階
wire n_lrck = ~lrck;
always @ (posedge lrck or posedhe n_lrck or posedge bck)
// 処理
2つ目のn_lrckはnegedge lrckとすればよいと思ったかもいるかと思いますが、それもエラーでした。
ただし、上記だけでは、bckの立上りで完了パルスをクリアしたいのですが、これでもまだ不完全です。
lrckの変化で呼ばれたのかbckの変化で呼ばれたのかが判断できないためです。
ですので、下記のように改良します。
//第2段階
always @ (posedge bck)
if (done)
done_clr <= 1'h1;
else
done_clr <= 1'h0;
always @ (posedge lrck or posedge n_lrck or posedge done_clr)
if (done_clr)
done <= 1'h0;
else
done <= 1'h1;
//データラッチはdoneの立ち上がりエッジで
少々ややこしいですが、じっくり考えればわかると思います。
分からないという方のために解説します。
bckの立下りでクリアしたいのでbckの立上り時に完了フラグ(done)が立っているときはクリアフラグ(done_clr)をあげます。
クリアフラグが上がったときは完了フラグをクリアします。
それいがいのLRCKの立ち上がり立下りで呼ばれたときは完了フラグを上げます。
また完了フラグが下がっている場合はクリアフラグもクリアします。
↓の図はModel-simでもシミュレート結果(lrckの立下りだけですが、立ち上がりも同様)
ご参考まで~