電卓などにはたくさんのキーがありますが、押されたキーの番号を符号化するための論理モジュールをエンコーダといいます。このモジュールは、押されたキー番号に対応するビットだけが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でした。