2021年1月10日日曜日

verilog : 除算器2( 商を 固定小数点化 )

目的: 

商を固定小数点とした除算器の構成、RTLについて記す。

仕様:

本除算器は、
  1. 演算は 16bit ÷ 16bit の符号なし整数の除算で、出力は 32bit 固定小数点(u16.16) の商
  2. 複数クロックを使用して演算を行う。
  3. 開始パルスで演算を開始し、演算終了で終了信号を出力する。

除算方法:

除算器 と同様。
違いは、
  1. 商の bit幅を 32bit に拡張 (整数部 16bit, 小数部 16bit の 固定小数点 )
  2. 繰り返し回数を 32回に増加 (商が 32bit の為)
  3. 剰余は削除
のみ。

ブロック図:

除算器のブロック図を以下に示す。

RTL:

上述のブロック図 の RTL を以下に示す。
// ----------------------------------------------------------------------------
//  Divider 
//
//   Module Name : divid
//   Version     : 0.00
// ----------------------------------------------------------------------------
 
module divid (                          // Module name : divid
  CLR,                                  // port list
  CLK,
  a,
  b,
  start,
  division,
  complete
) ;
 
// port declaration ----------------
input              CLR      ;
input              CLK      ;
input       [15:0] a        ;
input       [15:0] b        ;
input              start    ;
output reg  [31:0] division   ;
output reg         complete ;
 
// parameter declaration -----------
parameter P_DLY = 1 ;
 
// internal signal declaration -----
wire        op_cnt_en   ;
wire        borrow      ;
wire [17:0] sub         ;
wire        div_en      ;

reg   [5:0] op_cnt      ;
reg  [32:0] div_ref     ;
reg  [31:0] div_val     ;

// logical description -------------

assign op_cnt_en = (op_cnt < 6'd32) ;

always @(posedge CLK or posedge CLR)
  if (CLR)
    op_cnt <= #P_DLY 6'd63 ;
  else if (start)
    op_cnt <= #P_DLY 6'd0 ;
  else if (op_cnt_en)
    op_cnt <= #P_DLY op_cnt + 6'd1 ;

always @(posedge CLK or posedge CLR)
  if (CLR)
    div_ref <= #P_DLY 32'd0 ;
  else if (start)
    div_ref <= #P_DLY {16'b0,a} ;
  else if (~borrow & div_en)
    div_ref <= #P_DLY {sub[15:0],div_ref[14:0],1'b0} ;
  else if (div_en)
    div_ref <= #P_DLY div_ref << 1 ;

assign sub = {1'b0,div_ref[31:15]} - {2'b0,b} ;
assign borrow = sub[17] ;

assign div_en = (op_cnt <= 6'd31) ;

always @(posedge CLK or posedge CLR)
  if (CLR)
    div_val <= #P_DLY 32'd0 ;
  else if (start)
    div_val <= #P_DLY 32'd0 ;
  else if (div_en)
    div_val <= #P_DLY {div_val[30:0],~borrow} ;

always @(posedge CLK or posedge CLR)
  if (CLR)
    complete <= #P_DLY 1'b0 ;
  else 
    complete <= #P_DLY (op_cnt == 6'd32) ;

always @(posedge CLK or posedge CLR)
  if (CLR)
    division <= #P_DLY 32'd0 ;
  else 
    division <= #P_DLY div_val ;

endmodule

動作結果:

本回路のシミュレーション結果 を以下に示す。

除算結果(商) は 整数部 16bit, 少数部 16bit の為、1/2^16 = 0.00001526 の誤差がある。
255/1023 の シミュレーション結果は 0.249252 で 計算値 0.249266862 とは
0.000014862 の差があるが、これは誤差範囲内。



0 件のコメント:

コメントを投稿