2020年12月27日日曜日

verilog : 乗算器

 目的: 

乗算器の構成、RTLについて記す。

仕様:

本乗算器は、
  1. 演算は 16bit X 16bit の符号なしの乗算で、出力は 32bit
  2. 複数クロックを使用して演算を行い、回路規模、遅延時間の削減を図る。
  3. 開始パルスで演算を開始し、演算終了で終了信号を出力する。

ブロック図:

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

ブロック図 1

16x16 乗算器_1

本回路の動作は以下の通り。
被乗数(a) に 乗数(b) を掛ける。
b の 各bit(桁) と a を掛けた(AND)結果(pd)を、各bit(桁)に応じてシフトし、1サイクル毎に加算していく。
op_cnt は pd を選択する為のカウンタで start 入力によりカウントを開始し、1サイクル毎に 加算する pd を選択する。
start から 乗数(b)のビット数分のカウントを行う間、加算のイネーブル(add_en)を生成して pd の加算を繰り返す。
乗数(b)のビット数分の加算が終了したら終了信号(complete) を出力する。

ブロック図 2

16x16 乗算器_2

本回路は、上のブロック図 1 の 回路規模削減を目指した修正版。
動作はブロック図 1と同様。
サイクル毎の選択は 乗数(b)のbit(桁) 選択を行い、選択後に 被定数(a)との乗算(AND) を行うことで AND 回路を 削減。
加算は乗算結果のbit数に1bitのbit拡張したbit数で行うことで 加算器の bit数を削減。
加算結果は 1bit シフトしながら FF に記憶していく。

RTL:

上述のブロック図 2 の RTL を以下に示す。
// ----------------------------------------------------------------------------
//   16 x 16 bit Multiplier 
//
//   Module Name : mult_16
//   Version     : 0.00
// ----------------------------------------------------------------------------
 
module mult_16 (                        // Module name : mult_16
  CLR,                                  // port list
  CLK,
  a,
  b,
  start,
  result,
  complete
) ;
 
// port declaration ----------------
input              CLR      ;
input              CLK      ;
input       [15:0] a        ;
input       [15:0] b        ;
input              start    ;
output reg  [31:0] result   ;
output             complete ;
 
// parameter declaration -----------
parameter P_DLY = 1 ;
 
// internal signal declaration -----
wire        op_cnt_en   ;
wire        op_cnt_last ;
wire        pb          ;
wire [15:0] add_val     ;
wire [16:0] pval        ;

reg   [4:0] op_cnt      ;
reg         add_en      ;
 
// logical description -------------

assign op_cnt_en   = op_cnt <  5'd16 ; 
assign op_cnt_last = op_cnt == 5'd15 ; 

always @(posedge CLK or posedge CLR)
  if (CLR) 
    op_cnt  <= #P_DLY  5'h1f ;
  else if (start)
    op_cnt  <= #P_DLY  5'h0  ;
  else if (op_cnt_en)
    op_cnt  <= #P_DLY  op_cnt + 5'd1 ;

always @(posedge CLK or posedge CLR)
  if (CLR)
    add_en <= #P_DLY 1'b0 ;
  else if (op_cnt_last)
    add_en <= #P_DLY 1'b0 ;
  else if (start)
    add_en <= #P_DLY 1'b1 ;

assign pb   = (op_cnt == 5'd0  ) ? b[0] :
              (op_cnt == 5'd1  ) ? b[1] : 
              (op_cnt == 5'd2  ) ? b[2] : 
              (op_cnt == 5'd3  ) ? b[3] : 
              (op_cnt == 5'd4  ) ? b[4] : 
              (op_cnt == 5'd5  ) ? b[5] : 
              (op_cnt == 5'd6  ) ? b[6] : 
              (op_cnt == 5'd7  ) ? b[7] : 
              (op_cnt == 5'd8  ) ? b[8] : 
              (op_cnt == 5'd9  ) ? b[9] : 
              (op_cnt == 5'd10 ) ? b[10]: 
              (op_cnt == 5'd11 ) ? b[11]: 
              (op_cnt == 5'd12 ) ? b[12]: 
              (op_cnt == 5'd13 ) ? b[13]: 
              (op_cnt == 5'd14 ) ? b[14]: 
              (op_cnt == 5'd15 ) ? b[15]: 1'bx ;

assign add_val = a & {16{pb}} ;

assign pval = {1'b0,result[31:16]} + {1'b0, add_val} ;

always @(posedge CLK or posedge CLR)
  if (CLR)
    result <= #P_DLY 32'h0 ;
  else if (start)
    result <= #P_DLY 32'h0 ;
  else if (add_en)
    result <= #P_DLY {pval,result[15:1]} ;

assign complete = op_cnt == 5'd16 ;


endmodule

動作結果:

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




0 件のコメント:

コメントを投稿