整数どうしの除算の場合、商と余りを求めることが要求されることもありますが、比率などを求める際には、小数点以下n桁までの結果が要求されます。比率“numerator/denominater”を小数点以下16ビットまで求めるモジュールを以下に示します。
module div_4_state( input [15:0] numerator, input [15:0] denominator, output reg [15:0] surplus, output reg [31:0] quotient_p16, input clock); reg [2:0] state; reg [31:0] num, q; reg [15:0] den; wire [31:0] s4; wire [3:0] q4; unsigned_div4 u1(.num4(num), .den4(den), .s4(s4), .q4(q4)); always @(posedge clock) begin state <= state + 3'h1; case (state) 3'h0: begin num <= {16'h0, numerator}; den <= denominator; quotient_p16 <= {q[27:0], q4}; surplus <= s4[31:16]; end default: begin num <= s4; q <= {q[27:0], q4}; end endcase end endmodule
シミュレーション結果を下図に示します。この例では12(16進でC000)を1から9までの整数で割った結果を、小数点以下16ビットまで求めています。結果(quotient_p16)は16進表示されていますので、下位の4つの数字が少数部、上位の4つの数字が整数部となります。
比率quotient_p16は、上位16ビットが整数部、下位16ビットが小数部を意味し、数字で表現する際にはビット16の右側に小数点を記入することになります。このような小数点の位置が定まっている数値表現を「固定小数点数」と呼びます。
固定小数点数は、Verilog言語自体に備わった型ではなく、利用者が意識して取り扱う必要があります。そこで、この文書では、小数部が16ビットある固定小数点数の変数名は末尾に_p16を付けることといたします。上の例では“quotient_p16”がこれにあたり、下位16ビットが小数部であること、あるいは、ビット16の右側に小数点があることを示しています。
固定小数点数のもう一つのタイプとして、整数の下位のゼロを省略したものがあります。たとえば下位16ビットのゼロを省略している場合は、変数名の末尾に_z16を付けることといたします。_p0と_z0は同じ意味であり、これを省略したものとも同じ値を意味します。これも、この文書内でのローカルルールです。
定数2±nの乗除算はシフト演算により行われることを以前述べましたが、信号線には何ら操作を加えずに、小数点の位置が変わっただけであるとみなすこともできます。すなわち、信号線xが整数である場合にこれを4で割る演算は、下位2ビットを小数部とみなすよう固定小数点の位置を変化させるだけで済みます。
上でローカルルールを規定した固定小数点の命名規則に従えば、xを4で割ることは、信号線につけられた変数名xをx_p2に付け替えることとなります。一般的に、zk ならm = +k、pk ならm = -kと、小数点位置を符号付きの整数mで表現するとき、2nを乗じる操作はmをnだけ増加する操作に相当します。