前書き:
このコラムは、デジタル フロントエンドの秋採用者向けに、高頻度の筆記面接で手で引き裂かれたコードの質問を記録することを目的としています。このコラムのすべての記事には、原理分析、コードと波形が提供されており、すべてのコードは私自身によって検証されています。
ディレクトリは次のとおりです。
1. デジタルICハンドティアコード分周器(任意の偶数分周)
2. デジタル IC ハンドティアコード分周器 (任意の奇数分周)
3. デジタル IC ハンドティアコード分周器 (任意の 10 進分周)
4.デジタルICハンドティアリングコード - 非同期リセットと同期リリース
5.デジタルICハンドティアコード - エッジ検出(立ち上がりエッジ、立ち下がりエッジ、ダブルエッジ)
6. デジタルICハンドティアリングコード列検出(ステートマシン書き込み方式)
7. デジタルICハンドティアリングコード列検出(シフトレジスタ書き込み方式)
8. デジタルICティアリングコード - 半加算器、全加算器
9. デジタル IC ハンド ティアリング コード - シリアルからパラレル、パラレルからシリアル
10.デジタルICハンドティアリングコード-データビット幅変換器(幅-狭幅、狭幅変換)
11. デジタル IC ハンド ティアリング コード - 有限状態マシン FSM - 飲料マシン
12.デジタルICハンドティアコード - ハンドシェイク信号(READY-VALID)
13. デジタル IC ハンド ティアリング コード - 水ハンドシェイク (ハンドシェイクを使用してパイプラインの中断と背圧の問題を解決します)
14. デジタル IC ハンド テアリング コード - Telink マイクロ筆記試験問題
15. デジタル IC 手引きコード - Pingtouge 技術最終面手引き本当の質問
16.デジタルICマニュアルティアリングコード-Zhaoyiイノベーション筆記試験実際の質問
17. デジタル IC ハンド ティアリング コード - Espressif Technology 筆記試験実際の問題 (4 回の頻度)
18. デジタル IC ティアリング コード - デュアルポート RAM (デュアルポート RAM)
...継続的に更新
ティアオフ コードに関するその他の質問については、Digital IC ティアオフ コード - 質問バンクにアクセスしてください。
トピックの説明
Verilog RTL による除算器の実装。16ビットA、8ビットB。C=A/B
ソリューション
ハードウェアでは、これらはすべて 2 進数であり、2 進数の除算は 10 進数の除算に似ており、シフトしてサイズを比較するプロセスです。
計算手順:
① 被除数の上位データと除数を比較し、前者>後者であれば、対応するビットの商を1として求め、その差から前者の余りを求めることができます。それ以外の場合、対応する商は 0 となり、前者は剰余として直接使用されます。
② 前ステップの剰余と被除数の残り1ビットデータを新しいデータにつなぎ、除数と比較することで、新たな商と剰余が得られます。
③ 被除数の下位桁も計算に加わるまで、②の処理を繰り返します。
たとえば、375/23 = 16'b0000_0001_0111_0111 / 8'b0001_0111
被除数の最初の桁を除数と比較すると、8'b0000_0000<8'b0001_0111、商は 0 となり、前者が剰余として使用されます。
次に、右に 1 ビットシフトした数値を取得して比較を続けます (8'b0000_0000< 8'b0001_0111)。商は 0 で、前者は引き続き剰余として使用されます。
次に、右に 1 ビットシフトした数値を取得して比較を続けます (8'b0000_0000< 8'b0001_0111)。商は 0 で、前者は引き続き剰余として使用されます。
次に、右に 1 ビットシフトした数値を取得して比較を続けます (8'b0000_0000< 8'b0001_0111)。商は 0 で、前者は引き続き剰余として使用されます。
次に、右に 1 ビットシフトした数値を取得して比較を続けます (8'b0000_0000< 8'b0001_0111)。商は 0 で、前者は引き続き剰余として使用されます。
次に、右に 1 ビットシフトした数値を取得して比較を続けます (8'b0000_0000< 8'b0001_0111)。商は 0 で、前者は引き続き剰余として使用されます。
次に、右に 1 ビットシフトした数値を取得して比較を続けます (8'b0000_0000< 8'b0001_0111)。商は 0 で、前者は引き続き剰余として使用されます。
次に、右に 1 ビットシフトした数値を取得して比較を続けます (8'b0000_0001< 8'b0001_0111)。商は 0 で、前者は引き続き剰余として使用されます。
次に、1 ビット右にシフトした数値を取得して比較を続けます (8'b0000_0010< 8'b0001_0111)。商は 0 で、前者は引き続き剰余として使用されます。
次に、右に 1 ビットシフトした数値を取得して比較を続けます。8'b0000_0101< 8'b0001_0111、商は 0 となり、前者は引き続き剰余となります。
次に、1 ビット右にシフトした数値を取得して比較を続けます (8'b0000_1011< 8'b0001_0111)。商は 0 で、前者は引き続き剰余として使用されます。
次に、1 ビット右にシフトした数値を取得して比較を続けます (8'b0001_0111<=8'b0001_0111)。商は 1 で、2 つの差が剰余として使用されます。
次に、1 ビット右にシフトした数値を取得して比較を続けます (8'b0000_0000<8'b0001_0111)。商は 0 で、前者が剰余として使用されます。
次に、1 ビット右にシフトした数値を取得して比較を続けます (8'b0000_0001<8'b0001_0111)。商は 0 で、前者は引き続き剰余として使用されます。
次に、1 ビット右にシフトした数値を取得して比較を続けます (8'b0000_0011<8'b0001_0111)。商は 0 で、前者は引き続き剰余として使用されます。
次に、1 ビット右にシフトした数値を取得して比較を続けます。8'b0000_0111<8'b0001_0111、商は 0、前者は引き続き剰余として使用され、比較は最後の桁に達し、出力結果が得られます。 : 商は 1<<4=16、余りは 8'b0000_0111=7 です。
したがって、計算は 375/23=16...7 となります。
コード
module divisor(
input [15:0] A ,
input [7:0] B ,
output [15:0] result ,
output [7:0] remain
);
reg [15:0] a_reg ;
reg [7:0] b_reg ;
reg [31:0] temp_a ; # 其实这里取16+8+1bit就够了,取32位是为了好看。
reg [31:0] temp_b ;
integer i;
always@(*)begin
a_reg = A;
b_reg = B;
end
always@(*)begin
temp_a = {16'h0,a_reg};
temp_b = {b_reg,16'h0};
for(i=0;i<16;i=i+1)begin
temp_a = temp_a <<1;
if(temp_a >= temp_b)begin
temp_a = temp_a-temp_b+1;
end
else begin
temp_a = temp_a;
end
end
end
assign remain = temp_a[31:16];
assign result = temp_a[15:0];
endmodule
テストベンチ
module divisor_tb();
reg [15:0] A ;
reg [7:0] B ;
wire [15:0] result ;
wire [7:0] remain ;
initial begin
#10
A <= 16'd375;
B <= 8'd23;
#10
A <= 16'd557;
B <= 8'd57;
end
divisor u_divisor(
.A (A) ,
.B (B) ,
.result (result) ,
.remain (remain)
);
endmodule
波形
式 1: 375/23=16...7
式 2: 557/57=9 …… 44
結果は私たちが検討したことと一致しています。