2021年1月6日水曜日

verilog : 除算器

目的: 

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

仕様:

本除算器は、
  1. 演算は 16bit ÷ 16bit の符号なし整数 の 除算で、出力は 商と剰余 各16bit
  2. 複数クロックを使用して演算を行う。
  3. 開始パルスで演算を開始し、演算終了で終了信号を出力する。

除算方法:

除算は、回復法により行う。
除算の方法を下図に示す。
除算の手順は、
  1. 被除数の上位に除数のbit数分の 0 拡張を、除数に 1bit の 0拡張を行う。
  2. 被除数の上位bit から 除数 を減算する。
  3. 減算できる場合 (ボローが発生しない場合) は、減算した結果で被除数の上位bit を置き換えて 1bit 左シフトし、減算できない場合(ボローが発生した場合) は 被除数の上位 bit の置き換えは行わずに 1bit 左シフトを行う。
  4. また、商(初期値 0) を 1bit 左シフトし、最下位bit を ボローの反転値 とする。
  5. 2~5 を 被除数のbit数(拡張前) 分繰り返して商を得る。
  6. また、繰り返し終了後の被除数の拡張部分の値が 剰余となる。
被除数 3bit, 除数 3bit で 5÷2 を演算した場合の例を以下に示す。
被除数 3bit の為、3回繰り返して 商と剰余を得る。
右側に対応する 2進数での 割り算 の筆算 を示している。

ブロック図:

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

動作は、上述の除算方法の通り。

RTL:

上述のブロック図 の RTL を以下に示す。
divid.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// ----------------------------------------------------------------------------
//  Divider
//
//   Module Name : divid
//   Version     : 0.00
// ----------------------------------------------------------------------------
  
module divid (                          // Module name : divid
  CLR,                                  // port list
  CLK,
  a,
  b,
  start,
  division,
  remainder,
  complete
) ;
  
// port declaration ----------------
input              CLR      ;
input              CLK      ;
input       [15:0] a        ;
input       [15:0] b        ;
input              start    ;
output reg  [15:0] division   ;
output reg  [15:0] remainder  ;
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   [4:0] op_cnt      ;
reg  [32:0] div_ref     ;
reg  [15:0] div_val     ;
 
// logical description -------------
 
assign op_cnt_en = (op_cnt < 6'd16) ;
 
always @(posedge CLK or posedge CLR)
  if (CLR)
    op_cnt <= #P_DLY 5'd31 ;
  else if (start)
    op_cnt <= #P_DLY 5'd0 ;
  else if (op_cnt_en)
    op_cnt <= #P_DLY op_cnt + 5'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 <= 5'd15) ;
 
always @(posedge CLK or posedge CLR)
  if (CLR)
    div_val <= #P_DLY 16'd0 ;
  else if (start)
    div_val <= #P_DLY 16'd0 ;
  else if (div_en)
    div_val <= #P_DLY {div_val[14:0],~borrow} ;
 
always @(posedge CLK or posedge CLR)
  if (CLR)
    complete <= #P_DLY 1'b0 ;
  else
    complete <= #P_DLY (op_cnt == 5'd16) ;
 
always @(posedge CLK or posedge CLR)
  if (CLR)
    division <= #P_DLY 16'd0 ;
  else
    division <= #P_DLY div_val ;
 
always @(posedge CLK or posedge CLR)
  if (CLR)
    remainder <= #P_DLY 16'd0 ;
  else
    remainder <= #P_DLY div_ref[31:16] ;
 
endmodule

動作結果:

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


0 件のコメント:

コメントを投稿