電卓などにはたくさんのキーがありますが、押されたキーの番号を符号化するための論理モジュールをエンコーダといいます。このモジュールは、押されたキー番号に対応するビットだけが1となっている信号を入力して、1が立っている最上位のビット番号を2進数で出力します。
キーが一つも押されていないときはエラー信号線をHとして通知します。複数の信号線のいずれか1本だけがHとなるような信号線の使い方は「ワンホット」とも呼ばれ、キー入力以外にもさまざまな局面で使われています。
ノーマライザは、正規化処理をおこなう論理モジュールで、入力信号を最上位に1が現れるまで左シフトしてその結果とシフトした数を出力します。入力信号のビットがすべてゼロである場合はエラー信号線をHとします。
エンコーダとノーマライザは同じ論理モジュールで実現されます。コードの一例を以下に示します。
module dec_normal( input [15:0] in_p, output reg [3:0] code_p, output reg [15:0] normal_p, output reg error_p, input clock); reg [15:0] in; wire [3:0] code; wire[15:0] normal; wire error; always@(posedge clock) begin in <= in_p; code_p <= code; normal_p <= normal; error_p <= error; end decode u1(.in(in), .code(code), .normal(normal), .error(error)); endmodule module decode( input [15:0] in, output [3:0] code, output [15:0] normal, output error); assign code[3] = ~|in[15:8]; wire [15:0] work1 = code[3] ? {in[7:0], 8'h0} : in; assign code[2] = ~|work1[15:12]; wire [15:0] work2 = code[2] ? {work1[11:0], 4'h0} : work1; assign code[1] = ~|work2[15:14]; wire [15:0] work3 = code[1] ? {work2[13:0], 2'h0} : work2; assign code[0] = ~work3[15]; assign normal = code[0] ? {work3[14:0], 1'b0} : work3; assign error = ~normal[15]; endmodule
モジュール“decode”のおこなっていることは単純で、まず上位8ビットが0の場合は左に8ビットシフトしてcodeの最上位ビットを立てます。次にシフト結果の上位4ビットが0の場合は更に左に4ビットシフトしてcodeの二番目のビットを立てます。これを順に繰り返すことで、上位にゼロがある間左シフトを繰り返し、シフトした数がcodeにセットされることになります。
入力信号がゼロでない場合は最大15ビット左シフトすれば最上位のビットが1となります。そうならない場合は、入力信号のビットがすべてゼロであることを意味しますので、エラー信号をHとします。エラー信号は出力信号“normal”の最上位ビットを反転したものですから、あえてモジュールの出力信号とする必要もありませんが、上のサンプルコードでは、理解しやすいように、独立した信号線としています。
このモジュールをQualtus IIでコンパイルして形成されたRTLチャートを下図に示します。
モジュールの入り口と出口にレジスタを配置し遅延時間を測定した結果、遅延時間は約7ns、最高クロック周波数は142MHzとなりました。また、消費されたロジックエレメントの数は全部で68でした。