前言:
本專欄旨在記錄高頻筆面試手撕代碼題,以備數字前端秋招,本專欄所有文章提供原理分析、代碼及波形,所有代碼均經過本人驗證。
目錄如下:
1.數字IC手撕代碼-分頻器(任意偶數分頻)
2.數字IC手撕代碼-分頻器(任意奇數分頻)
3.數字IC手撕代碼-分頻器(任意小數分頻)
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手撕代碼-泰淩微筆試真題
15.數字IC手撕代碼-平頭哥技術終面手撕真題
16.數字IC手撕代碼-兆易創新筆試真題
17.數字IC手撕代碼-樂鑫科技筆試真題(4倍頻)
18.數字IC手撕代碼-雙端口RAM(dual-port-RAM)
...持續更新
更多手撕代碼題可以前往 數字IC手撕代碼--題庫。
題目描述
除法器的Verilog RTL實作。16bitA,8bitB。C=A/B
解決思路
在硬體中都是二進制數,二進制除法和十進制除法類似,都是一個移位并比較大小的過程。
計算步驟:
① 将被除數高位資料與除數作比較,如果前者>=後者,則可得到對應位的商為1,兩者做差得到第一步的餘數;否則得到對應的商為0,将前者直接作為餘數。
② 将上一步中的餘數與被除數剩餘最高位1bit資料拼接成新的資料,然後再和除數做比較,可以得到新的商和餘數。
③ 重複過程②,直到被除數最低位資料也參與計算。
舉個例子375/23 = 16'b0000_0001_0111_0111 / 8'b0001_0111
- 取被除數的第1位,與除數相比,8'b0000_0000<8'b0001_0111,商為0,前者作為餘數。
- 再取右移一位的數繼續比較,8'b0000_0000< 8'b0001_0111,商為0,前者繼續作為餘數。
- 再取右移一位的數繼續比較,8'b0000_0000< 8'b0001_0111,商為0,前者繼續作為餘數。
- 再取右移一位的數繼續比較,8'b0000_0000< 8'b0001_0111,商為0,前者繼續作為餘數。
- 再取右移一位的數繼續比較,8'b0000_0000< 8'b0001_0111,商為0,前者繼續作為餘數。
- 再取右移一位的數繼續比較,8'b0000_0000< 8'b0001_0111,商為0,前者繼續作為餘數。
- 再取右移一位的數繼續比較,8'b0000_0000< 8'b0001_0111,商為0,前者繼續作為餘數。
- 再取右移一位的數繼續比較,8'b0000_0001< 8'b0001_0111,商為0,前者繼續作為餘數。
- 再取右移一位的數繼續比較,8'b0000_0010< 8'b0001_0111,商為0,前者繼續作為餘數。
- 再取右移一位的數繼續比較,8'b0000_0101< 8'b0001_0111,商為0,前者繼續作為餘數。
- 再取右移一位的數繼續比較,8'b0000_1011< 8'b0001_0111,商為0,前者繼續作為餘數。
- 再取右移一位的數繼續比較,8'b0001_0111<=8'b0001_0111,商為1,兩者之差作為餘數。
- 再取右移一位的數繼續比較,8'b0000_0000<8'b0001_0111,商為0,前者作為餘數。
- 再取右移一位的數繼續比較,8'b0000_0001<8'b0001_0111,商為0,前者繼續作為餘數。
- 再取右移一位的數繼續比較,8'b0000_0011<8'b0001_0111,商為0,前者繼續作為餘數。
- 再取右移一位的數繼續比較,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
testbench
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
結果與我們考慮的一緻。