4.2.2 4to1セレクタ 4to1セレクタ din[0] din[1] din[2] din[3] dout sel 2 図4.9 4to1セレクタ 4本の信号から1本を選択する 「4to1セレクタ」を記述する。 図4.9にブロック図を示す。4ビッ ト入力din[3:0]から、2ビット の選択信号sel[1:0]によって1本 を選択し、doutに出力する。 sel[1:0]信号と入力din[3:0]の選 択の対応は sel= =2’b00 ・・・din[0] sel= =2’b01 ・・・din[1] sel= =2’b10 ・・・din[2] sel= =2’b11 ・・・din[3] を選択 を選択 を選択 を選択 条件演算子による4to1セレクタ //条件演算子による4to1セレクタ module sel4to1_cond(din,sel,dout); input[3:0] din; input[1:0] sel; output dout; assign dout = (sel==2'h0)? din[0]: (sel==2'h1)? din[1]: (sel==2'h2)? din[2]: din[3]; endmodule 条件演算子 ~?~:~を3個用いた4to1セレクタ。 条件演算子は入れ子構造(ネスティン グ)が可能。条件演算子では、条件式 が真のときは?直後の値を、偽のとき は:直後の値を演算結果とする。これ により if~ else if ~ else ~ を実現したことになる。 assign文一つで記述できるので一見簡潔。だが、選択される信号に論理式やファンクション が入ってくると記述の可能性は低下する。また、論理合成ツールによっては、回路規模が 大きくなってしまうことがある。 if文による4to1セレクタ //if文による4to1セレクタ module sel4to1_if(din,sel,dout); input [3:0] din; input [1:0] sel; output dout; function select; input [3:0] din; input [1:0] sel; if (sel==2'h0) select=din[0]; else if (sel==2'h1) select=din[1]; else if (sel==2'h2) select=din[2]; else select=din[3]; endfunction assign dout=select(din,sel); endmodule ここではif文を用いて、選択信号selの値を順次 比較する。一致した時点で、ファンクションselect の戻り値を確定する。if~else if ~構造で一つ のif文を形成している。 if文による4to1セレクタ function select; input [3:0] din; input [1:0] sel; if (sel==2'h0) select=din[0]; else if (sel==2'h1) select=din[1]; else if (sel==2'h2) select=din[2]; else select=din[3]; endfunction function select; input [3:0] din; input [1:0] sel; begin if (sel==2'h0) select=din[0]; if (sel==2'h1) select=din[1]; if (sel==2'h2) select=din[2]; if (sel==2'h3) select=din[3]; end endfunction sel信号の起こりうる全て の状態を記述している のでこのように複数のif 文に分割できる。 begin~endは順次処理 ブロックと呼ばれている。 functionの中では input などの宣言はいくつでも 記述できるが、実効部 は一文だけ許される。し たがってこのように複数 の文を記述する場合は begin~endで囲む。 case文による4to1セレクタ //case文による4to1セレクタ module sel4to1_case(din,sel,dout); input [3:0] din; input [1:0] sel; output dout; function select; input [3:0] din; input [1:0] sel; case(sel) 2'h0: select=din[0]; 2'h1: select=din[1]; 2'h2: select=din[2]; 2'h3: select=din[3]; default:select=1'bx; endcase endfunction assign dout=select(din,sel); endmodule 多方向のセレクタについては、case文 を用いるとまとまる。 選択信号selと一致したラベルの行だけ を実行する。見通しがよいので、多方向 のセレクタでは、もっぱらcase文を用いる。 ビット選択による4to1セレクタ //ビット選択による4to1セレクタ module sel4to1_bitsel(din,sel,dout); input [3:0] din; input [1:0] sel; output dout; assign dout=din[sel]; endmodule 図4.9の4to1セレクタを実現する場合、 おそらくビット選択による方法が一番シ ンプルな記述スタイル。 多ビット信号のビット選択には、定数だけ でなく変数を用いる事ができる。 4ビットの入力din[3:0]の1ビットを選択する時 assign dout=din[sel]; とすれば、選択信号selによって指定される 1ビットだけを選択できる。 3to1セレクタ 3本の信号から1本を選択し 出力する. din[0] din[1] dout din[2] sel 2 図4.14 3to1セレクタ if文による3to1セレクタ //if文による3to1セレクタ module sel3to1_if( din, sel, dout ); input [2:0] din; input [1:0] sel; output dout; function select; input [2:0] din; input [1:0] sel; if ( sel==2'h0 ) select = din[0]; else if ( sel==2'h1 ) select = din[1]; else select = din[2]; endfunction assign dout = select( din, sel ); endmodule 図4.15 if文による3to1セレクタ 図4.11の4to1セレクタ からsel==2’b11の場合 を取り除いただけ case文による3to1セレクタ //case文による3to1セレクタ module sel3to1_case( din, sel, dout ); input [2:0] din; input [1:0] sel; output dout; function select; input [2:0] din; input [1:0] sel; case ( sel ) 2'h0: select 2'h1: select 2'h2, 2'h3: select default: select endcase endfunction = = = = din[0]; din[1]; din[2]; 1'bx; 図4.16 case文による3to1セレクタ 2'h2: select = din[2]; 2'h3: select = din[2]; case ( sel ) 2'h0: 2'h1: default: endcase select = din[0]; select = din[1]; select = 1'bx; assign dout = select( din, sel ); 図4.15のif文による3to1と同一 endmodule casex文による3to1セレクト //casex文による3to1セレクト //caxex文による3to1セレクト module sel3to1_casex( din, sel, dout ); input [2:0] din; input [1:0] sel; output dout; 図4.17 function select; input [2:0] input [1:0] casex ( sel 2'b00: 2'b01: 2'b1x: 2'b1?: endcase endfunction x、yを比較対象外にできる. din; sel; ) select = din[0]; select = din[1]; select = din[2]; casez文による3to1セレクタ casex文 図4.18 3種類のcase文の動作 case x,xも含めて一致比較 casez zはdon’t care casex x,zはdon’t’care assign dout = select( din, sel ); endmodule ?をzと同じ意味に用いることもできる. 4.4 エンコーダ 藤井研究室 杉田 陽市 エンコーダの仕様 8入力のプライオリティ・エンコーダ 真理値表 din [7] din [6] din [5] din [4] din [3] din [2] din [1] din [0] 優 先 順 位 高 dout [2] dout [1] dout [0] din [7:0] dout [2:0] 1xxxxxxx 01xxxxxx 001xxxxx 0001xxxx 00001xxx 000001xx 0000001x 0000000x 7 6 5 4 3 2 1 0 8個の1bit入力din[0]~din[7]から3bitのdoutを出力 dinのいずれか1ビットのみ'1'であることが前提 複数の入力が同時に'1'になっても出力を確定させるため,優先順位を付けてある dinのMSB側の優先順位が高い 例 din: 11000000 → dout: 7 din: 01010000 → dout: 6 4.4.1 if文によるエンコーダ if文によるエンコーダ module encoder_if( din, dout); input [7:0] din; output [2:0] dout; function [2:0] enc; input [7:0] din; if (din[7]) enc = 3'h7; else if (din[6]) enc = 3'h6; else if (din[5]) enc = 3'h5; else if (din[4]) enc = 3'h4; else if (din[3]) enc = 3'h3; else if (din[2]) enc = 3'h2; else if (din[1]) enc = 3'h1; else enc = 3'h0; endfunction assign dout = enc(din); endmodule ③ ① ① モジュールとポートの宣言 入力 8bit din 出力 3bit dout ② ファンクション encの定義 入力 8bit din 戻り値 3bit else if ~ 構造でdinの上位ビットから比較す ることで優先順位を付ける 上位ビットが'1'であれば戻り値確定 ② if (din[7]) ・・・0,'x','z'のとき偽,0以外のとき真 if (din[7] == 1'b1)と同様 ③ encの呼び出しとその結果のdoutへの代入 4.4.2 casex文によるエンコーダ casex文 casex文によるエンコーダ module encoder_casex( din, dout); input [7:0] din; output [2:0] dout; function [2:0] enc; input [7:0] din; casex (din) 8'b1xxx_xxxx: 8'b01xx_xxxx: 8'b001x_xxxx: 8'b0001_xxxx: 8'b0000_1xxx: 8'b0000_01xx: 8'b0000_001x: 8'b0000_000x: endcase endfunction enc enc enc enc enc enc enc enc = = = = = = = = 3'h7; 3'h6; 3'h5; 3'h4; 3'h3; 3'h2; 3'h1; 3'h0; 使い方はcase文と同様 'x'の付いているビットは比較しない casex (din) 8'b1xxx_xxxx: enc = 3'h7; dinの8bit目(din[7])が1の場合, 3bit16進数の7を戻り値として返す 下位7bitは比較しない _(アンダーバー)の有無,位置,個数は任意 assign dout = enc(din); endmodule 特徴 If文によるものと比べ 可読性が良い 記述が簡潔 4.4.3 for文によるエンコーダ for文によるエンコーダ module encoder_for( din, dout); input [7:0] din; output [2:0] dout; function [2:0] enc; input [7:0] din; integer i; begin: LOOP enc = 0; for( i=7; i>=0; i=i-1) if (din[i]) begin enc = i; disable LOOP; end end endfunction integer i 符号付きの32bit整数 begin: LOOP ・ ・ ・ end begin~endで囲まれた順次処理 ブロックにラベル(名前)を付加 iを7から0まで変化させ,din[i]を上位ビットから比較 din[i]が1であった時点でencの戻り値を確定 assign dout = enc(din); endmodule disable LOOP; 名前付きブロックLOOPから抜け出す 特徴 ソフトウェアに近い記述スタイル 可読性が悪い 実際には使用しないほうが無難 4.4.4 always文によるエンコーダ always文によるエンコーダ module encoder_always( din, dout); input [7:0] din; output [2:0] dout; reg [2:0] dout; integer i; always @(din) begin: LOOP dout = 0; for ( i=7; i>=0; i=i-1) if (din[i]) begin dout = i; discable LOOP; end end for文を用いたエンコーダのfunctionをalwaysに置き換えた もの reg [2:0] dout; always文の中の代入にはネット宣言 した信号を用いることが出来ないため, doutをレジスト宣言 always @(din) 8bitの入力dinの内1bitでも変化したら, 常にalways以降を実行 入力が変化したら,すぐに出力の変化となる endmodule レジスタ変数を用いても組み合わせ回路となる 特徴 forループによるものに比べ,さらに可読性が悪い 実際には使用しないほうが無難 まとめ 今回説明した4つの記述法全てについてシミュレーションにより正常に動作することを確認した casex文によるエンコーダが最良の記述法である
© Copyright 2024 ExpyDoc