4.2.2 4to1セレクタ
4to1セレクタ din[0] din[1] dout din[2] din[3] sel 2 図4.9 4to1セレクタ の選択信号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セレクタ endfunction //if文による4to1セレクタ assign dout=select(din,sel); endmodule //if文による4to1セレクタ module sel4to1_if(din,sel,dout); input [3:0] din; input [1:0] sel; output dout; function select; 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]; ここではif文を用いて、選択信号selの値を順次 比較する。一致した時点で、ファンクションselect の戻り値を確定する。if~else if ~構造で一つ のif文を形成している。
if文による4to1セレクタ function select; 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; 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セレクタ 図4.9の4to1セレクタを実現する場合、 おそらくビット選択による方法が一番シ ンプルな記述スタイル。 多ビット信号のビット選択には、定数だけ でなく変数を用いる事ができる。 4ビットの入力din[3:0]の1ビットを選択する時 assign dout=din[sel]; とすれば、選択信号selによって指定される 1ビットだけを選択できる。 //ビット選択による4to1セレクタ module sel4to1_bitsel(din,sel,dout); input [3:0] din; input [1:0] sel; output dout; assign dout=din[sel]; endmodule
3to1セレクタ 3本の信号から1本を選択し 出力する. din[0] din[1] dout din[2] sel 2
if文による3to1セレクタ 図4.15 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セレクタ 図4.16 case文による3to1セレクタ 図4.15のif文による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 = din[0]; 2'h1: select = din[1]; 2'h2, 2'h3: select = din[2]; default: select = 1'bx; endcase endfunction assign dout = select( din, sel ); endmodule 図4.16 case文による3to1セレクタ 2'h2: select = din[2]; 2'h3: select = din[2]; case ( sel ) 2'h0: select = din[0]; 2'h1: select = din[1]; default: select = 1'bx; endcase 図4.15のif文による3to1と同一
casex文による3to1セレクト 図4.17 casez文による3to1セレクタ casex文 x、yを比較対象外にできる. //caxex文による3to1セレクト module sel3to1_casex( din, sel, dout ); input [2:0] din; input [1:0] sel; output dout; function select; input [2:0] din; input [1:0] sel; casex ( sel ) 2'b00: select = din[0]; 2'b01: select = din[1]; 2'b1x: select = din[2]; endcase endfunction assign dout = select( din, sel ); endmodule //casex文による3to1セレクト module sel3to1_casex( din, sel, dout ); input [2:0] din; input [1:0] sel; output dout; function select; input [2:0] din; input [1:0] sel; casex ( sel ) 2'b00: select = din[0]; 2'b01: select = din[1]; 2'b1?: select = din[2]; endcase endfunction assign dout = select( din, sel ); endmodule 図4.17 casez文による3to1セレクタ casex文 x、yを比較対象外にできる. 図4.18 3種類のcase文の動作 case x,xも含めて一致比較 casez zはdon’t care casex x,zはdon’t’care ?をzと同じ意味に用いることもできる.
4.4 エンコーダ 藤井研究室 杉田 陽市
エンコーダの仕様 8入力のプライオリティ・エンコーダ dout [2:0] 1xxxxxxx 01xxxxxx 001xxxxx 7 6 5 4 3 2 1 din [7:0] 真理値表 din [7] din [6] din [5] din [4] din [3] din [2] din [1] din [0] dout [2] dout [1] dout [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文によるエンコーダ ① モジュールとポートの宣言 入力 8bit din ① ② ③ if文によるエンコーダ module encoder_if( din, dout); input [7:0] din; output [2:0] dout; function [2:0] enc; 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 else if ~ 構造でdinの上位ビットから比較することで優先順位を付ける 上位ビットが'1'であれば戻り値確定 if (din[7] == 1'b1)と同様 if (din[7]) ・・・0,'x','z'のとき偽,0以外のとき真 ③ encの呼び出しとその結果のdoutへの代入 ① モジュールとポートの宣言 入力 8bit din 出力 3bit dout ② ファンクション encの定義 戻り値 3bit
4.4.2 casex文によるエンコーダ casex文によるエンコーダ casex文 使い方はcase文と同様 module encoder_casex( din, dout); input [7:0] din; output [2:0] dout; function [2:0] enc; casex (din) 8'b1xxx_xxxx: enc = 3'h7; 8'b01xx_xxxx: enc = 3'h6; 8'b001x_xxxx: enc = 3'h5; 8'b0001_xxxx: enc = 3'h4; 8'b0000_1xxx: enc = 3'h3; 8'b0000_01xx: enc = 3'h2; 8'b0000_001x: enc = 3'h1; 8'b0000_000x: enc = 3'h0; endcase endfunction assign dout = enc(din); endmodule casex文 使い方はcase文と同様 'x'の付いているビットは比較しない casex (din) 8'b1xxx_xxxx: enc = 3'h7; dinの8bit目(din[7])が1の場合, 3bit16進数の7を戻り値として返す 下位7bitは比較しない _(アンダーバー)の有無,位置,個数は任意 If文によるものと比べ 可読性が良い 記述が簡潔 特徴
4.4.3 for文によるエンコーダ for文によるエンコーダ integer i 符号付きの32bit整数 begin: LOOP ・ module encoder_for( din, dout); input [7:0] din; output [2:0] dout; function [2:0] enc; integer i; begin: LOOP enc = 0; for( i=7; i>=0; i=i-1) if (din[i]) begin enc = i; disable LOOP; end endfunction assign dout = enc(din); endmodule integer i 符号付きの32bit整数 begin: LOOP ・ end begin~endで囲まれた順次処理 ブロックにラベル(名前)を付加 din[i]が1であった時点でencの戻り値を確定 iを7から0まで変化させ,din[i]を上位ビットから比較 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 endmodule for文を用いたエンコーダのfunctionをalwaysに置き換えた もの always文の中の代入にはネット宣言 した信号を用いることが出来ないため, doutをレジスト宣言 reg [2:0] dout; 8bitの入力dinの内1bitでも変化したら, 常にalways以降を実行 always @(din) 入力が変化したら,すぐに出力の変化となる レジスタ変数を用いても組み合わせ回路となる forループによるものに比べ,さらに可読性が悪い 実際には使用しないほうが無難 特徴
まとめ 今回説明した4つの記述法全てについてシミュレーションにより正常に動作することを確認した casex文によるエンコーダが最良の記述法である