部品:AXIストリームレジスタ [AXI]
AXIストリームの単純なリピーターを作ってみます。
プロトコルでは無く、タイミングを考えるレイヤーです。
受け取ったデータをラッチしてそのまま出力するだけ。(その1)で経路を分割するときにレジスタを入れる、という話がありましたが、経路が長くなったときに周波数を出すために入れるレジスタにもなります。
単純なようですが、意外と奥が深いです。そしてこの部品がAXI設計時の要となります。これを作っておかないと色々行き詰まる事が後からわかりました。
経路を分ける、切るという意味合いで、DecoupleとかSliceとか呼んでます。
宣言はこんな感じ。outputのreg/wireは場合によって変わります。ホントはsouce、sinkという名前にしたいところですが、同じ「s」なので、slave、masterとなってます。
AXIのハンドシェイクのタイミングです。
タイミング
"ready"と"valid"の組み合わせなので、4パターンあります。
[valid,ready]="00"と"01"は一緒にして良いかも。
この波形からまず思いつくのはこんな回路。
回路1
"ready"がクロックイネーブルとして使われた、普通のパイプラインレジスタですね。これはこれで使います。DFFを複数段にしてn段のディレイとしても使います。
追記:この回路はAXIとしては使ってはいけません。デッドロックします。
しかし、経路分割としては不十分。"ready"が分割されてません。"ready"の経路が長いままでクリティカルパスになる可能性があります。また、"ready"がレジスタ出力かどうかは後段の"ready"出力によります。この回路では不明です。
あと、せっかくレジスタなのに、受け側が"ready=0"だと、レジスタが空いていても受け取れません。レジスタが空いてたら受け取ってく欲しいですよね。「レジスタが空いてる」=「"valid"が"0"」ですので、こうしてみます。
回路2
機能的には良さそうですが、この回路を入出力端で使ってはいけません。"ready"が組み合わせ出力です。色々弊害が起きます。他の回路でもこのパターンの回路を使うと、"ready"がクリティカルパスになります。"ready"が数珠つなぎになりますからね。
一工夫必要です。
感覚的には、使っちゃダメと言った回路2の方がAXIっぽいと思います。回路1では"valid"が"data"と同じ扱いですが、回路2では「レジスタ内のデータが有効だよ~」というフラグのような扱いになってます。考え方はこちらから発展してます。
"ready"をレジスタ出力にすると後段の"ready"入力から1クロック遅れます。後段が「待った」と言ってもそれが前段に伝わるのは1クロック後です。その間に前段の転送は成立してしまうので、どこかに保存しておかないといけません。ということで、「どこか」=もう一段データを保存するレジスタが必要になります。値が有効を示す"valid"ももう一本増えます。
続く
プロトコルでは無く、タイミングを考えるレイヤーです。
受け取ったデータをラッチしてそのまま出力するだけ。(その1)で経路を分割するときにレジスタを入れる、という話がありましたが、経路が長くなったときに周波数を出すために入れるレジスタにもなります。
単純なようですが、意外と奥が深いです。そしてこの部品がAXI設計時の要となります。これを作っておかないと色々行き詰まる事が後からわかりました。
経路を分ける、切るという意味合いで、DecoupleとかSliceとか呼んでます。
宣言はこんな感じ。outputのreg/wireは場合によって変わります。ホントはsouce、sinkという名前にしたいところですが、同じ「s」なので、slave、masterとなってます。
module axis_slice #( parameter dw = 0 // Data Width ) ( // common input wire c_clk, // clock input wire c_rst, // reset // stream-in, sink, write, slave output reg s_ready, // ready input wire s_valid, // valid input wire [dw-1:0] s_data , // data // stream-out, source, read, master input wire m_ready, // ready output reg m_valid, // valid output reg [dw-1:0] m_data // data ); /* 本体 */ endmodule
AXIのハンドシェイクのタイミングです。
タイミング
"ready"と"valid"の組み合わせなので、4パターンあります。
valid | ready | 状態 |
---|---|---|
0 | 0 | アイドル |
0 | 1 | アイドル(転送催促?) |
1 | 0 | ウェイト |
1 | 1 | 転送成立 |
この波形からまず思いつくのはこんな回路。
回路1
assign s_ready = m_ready; always @(posedge c_clk) begin if (c_rst) begin m_valid <= 1'b0; end else if (s_ready) begin m_valid <= s_valid; m_data <= s_data; end end
"ready"がクロックイネーブルとして使われた、普通のパイプラインレジスタですね。これはこれで使います。DFFを複数段にしてn段のディレイとしても使います。
追記:この回路はAXIとしては使ってはいけません。デッドロックします。
しかし、経路分割としては不十分。"ready"が分割されてません。"ready"の経路が長いままでクリティカルパスになる可能性があります。また、"ready"がレジスタ出力かどうかは後段の"ready"出力によります。この回路では不明です。
あと、せっかくレジスタなのに、受け側が"ready=0"だと、レジスタが空いていても受け取れません。レジスタが空いてたら受け取ってく欲しいですよね。「レジスタが空いてる」=「"valid"が"0"」ですので、こうしてみます。
回路2
assign s_ready = m_ready | ~m_valid; /*他同じ*/
機能的には良さそうですが、この回路を入出力端で使ってはいけません。"ready"が組み合わせ出力です。色々弊害が起きます。他の回路でもこのパターンの回路を使うと、"ready"がクリティカルパスになります。"ready"が数珠つなぎになりますからね。
一工夫必要です。
感覚的には、使っちゃダメと言った回路2の方がAXIっぽいと思います。回路1では"valid"が"data"と同じ扱いですが、回路2では「レジスタ内のデータが有効だよ~」というフラグのような扱いになってます。考え方はこちらから発展してます。
"ready"をレジスタ出力にすると後段の"ready"入力から1クロック遅れます。後段が「待った」と言ってもそれが前段に伝わるのは1クロック後です。その間に前段の転送は成立してしまうので、どこかに保存しておかないといけません。ということで、「どこか」=もう一段データを保存するレジスタが必要になります。値が有効を示す"valid"ももう一本増えます。
続く
2012-04-23 16:08
nice!(0)
コメント(0)
トラックバック(0)
コメント 0