Verilog 立ち上がり時の処理が1クロック遅れる疑問

Verilogの挙動が理解できないTT



まず、40MHzクロックTTC_CMOS40と、40MHz5クロックごとに立ち上がるL1Aを作った。そこで、L1Aが立ち上がると同時にL1ID_cntに1を入れ、続く40MHz2クロックで1, 2, 3までカウントアップしたい。しかし、L1Aの立ち上がりの1クロック後にL1IDに1が入る。なぜだ。。


    // set 40MHz clock
    initial begin
                          TTC_CMOS40 = 0;
        forever #(STEP/2) TTC_CMOS40 = ~TTC_CMOS40;
    end
 

    // for simulation put L1A signal for every 5 clocks
    initial l1a_clk <= 0;
    always @(posedge TTC_CMOS40) begin
        l1a_clk <= (l1a_clk==3'd4) ? 3'b0: l1a_clk + 3'b1;
        L1A     <= (l1a_clk==3'd4) ? 1'b1:           1'b0;
    end

    // L1ID takes 1 when L1A gets 1 and then takes 2, 3 at succeeding clocks.
    always @(posedge TTC_CMOS40 posedge L1A) begin
        L1ID_cnt <=  L1A               ? 3'b001:
                    (L1ID_cnt==3'b001) ? 3'b010:
                    (L1ID_cnt==3'b010) ? 3'b011:
                                         3'b000;



L1ID_cntが赤く落書きしたところで立ち上がっていてほしいのにTT

        L1ID_cnt <=  L1A ? 3'b001:

という行、L1Aが1ならL1IDに1入れることになってるのに、なぜ遅れてるんだ。


これでは、よくある同期リセット

always @(posedge clk) begin
    rgst <= reset ? 0 : 1
end

でも、resetが1になった1クロック後にrgstが0になるということか。

追記 (Aug 8, 2015):


これらの記事で原因が判明した。

L1A <= 1
L1ID_cng <= L1A

の処理の際に、l1ID_cntには1が代入される前のL1Aが使われていることに気付きました。ブロッキング代入 L1A = 1 してL1Aに真っ先に代入することで解決しそう。その検証は後述。しかし、実機とシミュレーションで動作が食い違うらしいとも聞く。


always @( posedge TTC_CMOS40 or posedge L1A)
とすることで、L1Aの立ち上がりと同時にL1ID_cntも立ち上がるようになりましたが、2ビット目の処理が、一周期遅れてしまう。条件のL1Aの評価が、立ち下がり前の1を使ってしまうからだろう。何て記述が難しいんだ。

この記述も、alwaysの中に posedge L1A が必要になる理由がよくわからない。というのも、L1Aが立ち上がるのとTTC_CMOS40が立ち上がるのは同時だからだ。


L1A へ1の代入がL1ID_cntよりも先であれば正常に動くはず。上記のL1Aへの代入をブロッキング代入

L1A = 1'b1;

にして再び実行してみた。


思ったとおりの動作をした。実機でもこのように動くのだろうか。


ただし、クロックもL1Aも外部から取り入れる予定なので、また再考が必要だろう。次は、データサイズが0を吐き出している問題の原因究明だ。

追記 (8月9日):
次の2つをassignすることで解決した。

L1A
000010000

L1ID_cnt
000002300

上記2つから

欲しかったもの。L1Aが来たら3カウントする。
000012300

コメント

人気の投稿