verilog實現(xiàn)除法器運算
本文通過verilog實現(xiàn)了一個位寬參數(shù)可配置的除法運算模塊
1, 設計思路
我們要計算 a_data/b_data = div_data ----remain_data;
-
?? 確定位寬:若a_data的位寬為A_WIDTH, b_data的位寬為B_WIDTH;則div_data的最大位寬為A_WIDTH, remain_data的位寬為B_WIDTH;
-
?? 計算div_data的最高位:若a_data >= (b_data<<(A_WIDTH-1)), 則div_data的最高位div_data[A_WIDTH-1]為1,否則div_data[A_WIDTH-1]為0; 即div_data[A_WIDTH-1] = a_data > (b_data<<(A_WIDTH-1)) ? 1‘b1 : 1’b0;
-
?? 計算div_data的次高位:若div_data的最高位div_data[A_WIDTH-1]為1,則a_data_tmp = a_data – (b_data<<(A_WIDTH-1)); 否則a_data_tmp = a_data; 次高位div_data[A_WIDTH-2] = a_data_tmp >= (b_data<<(A_WIDTH-2)) ? 1‘b1 : 1’b0;
-
?? 依次類推,可 計算出完整的div_data;
-
??. 計算完div_data后,可用 remain_data = a_data – b_data*div_data獲取余數(shù);
舉個例子,計算8/3 也就是 4’b1000/3’b011 = 3’b010;
-
?? div_data[3] = 4’b1000 > (3’b011 << 3) ? 1’b1 : 1’b0 ; 由于div_data[3]為0,所以a_data_tmp為4‘b1000;
-
?? div_data[2] = 4’b1000 > (3’b011 << 2) ? 1’b1 : 1’b0; 由于div_data[2]為0,所以a_data_tmp為4‘b1000;
-
?? div_data[1] = 4’b1000 > (3’b011 << 1) ? 1’b1 : 1’b0; 由于div_data[1]為1,所以a_data_tmp為4‘b1000-(3’b011 << 1) = 4’b0010;
-
?? div_data[0] = 4’b0010 > (3’b011 << 0) ? 1’b1 : 1’b0;
-
??所以 div_data = 4‘b0010 = 2;
-
?? remain_data = a_data – b_data*div_data = 8 – 3 * 2 = 2 = 3’b010;
2, Verilog代碼
// Filename : div.v
// Author : ppkuan
module div(/*autoarg*/
//Inputs
clk, rst_n, in_vld, a_data, b_data,
//Outputs
out_vld, remain_data, div_data
);
parameter A_WIDTH = 10;
parameter B_WIDTH = 5;
// a_data/b_data = div_data------remain_data
input clk ;
input rst_n ;
input in_vld ;
input [A_WIDTH - 1 : 0] a_data ;
input [B_WIDTH - 1 : 0] b_data ;
output reg out_vld ;
output reg [B_WIDTH - 1 : 0] remain_data ;
output reg [A_WIDTH - 1 : 0] div_data ;
wire [A_WIDTH - 1 : 0] div_data_tmp ;
wire [A_WIDTH - 1 : 0] [A_WIDTH + B_WIDTH - 1 : 0] ab_data_tmp ;
wire [A_WIDTH - 1 : 0] [A_WIDTH - 1 : 0] a_data_tmp ;
wire [B_WIDTH - 1 : 0] remain_data_tmp ;
assign ab_data_tmp[A_WIDTH - 1] = b_data << (A_WIDTH - 1);
assign div_data_tmp[A_WIDTH - 1] = {{B_WIDTH{1'b0}}, a_data} >= ab_data_tmp[A_WIDTH - 1] ? 1'b1 : 1'b0;
assign a_data_tmp[A_WIDTH - 1] = div_data_tmp[A_WIDTH - 1] ? {{B_WIDTH{1'b0}},a_data} - ab_data_tmp[A_WIDTH - 1] : a_data;
genvar i;
generate
for(i = A_WIDTH - 2; i >= 0; i--)
begin:div
assign ab_data_tmp[i] = (b_data << i);
assign div_data_tmp[i] = {{B_WIDTH{1'b0}}, a_data_tmp[i+1]} >= ab_data_tmp[i] ? 1'b1 : 1'b0;
assign a_data_tmp[i] = div_data_tmp[i] ? {{B_WIDTH{1'b0}},a_data_tmp[i+1]} - ab_data_tmp[i] : a_data_tmp[i + 1];
end
endgenerate
assign remain_data_tmp = {{B_WIDTH{1'b0}}, a_data} - div_data_tmp * b_data;
always@(posedge clk or negedge rst_n)
if(!rst_n)
begin
out_vld <= 'b0 ;
remain_data <= 'd0 ;
div_data <= 'd0 ;
end
else if(in_vld)
begin
out_vld <= 'b1 ;
remain_data <= remain_data_tmp;
div_data <= div_data_tmp ;
end
else
begin
out_vld <= 'b0 ;
end
endmodule
3, 測試用例:
module test;
wire clk ;
wire rst_n ;
wire in_vld ;
wire [9 : 0] a_data ;
wire [4 : 0] b_data ;
wire out_vld ;
wire [9 : 0] div_data ;
wire [4 : 0] remain_data ;
reg clk_r ;
reg rst_n_r ;
reg in_vld_r ;
reg [9 : 0] a_data_r ;
reg [4 : 0] b_data_r ;
assign clk = clk_r ;
assign rst_n = rst_n_r ;
assign in_vld = in_vld_r ;
assign a_data = a_data_r ;
assign b_data = b_data_r ;
div#(
.A_WIDTH(10),
.B_WIDTH(5))
u_div(/*autoinst*/
// a_data/b_data = div_data------remain_data
.clk (clk ), // input
.rst_n (rst_n ), // input
.in_vld (in_vld ), // input
.a_data (a_data[9 : 0] ), // input
.b_data (b_data[4 : 0] ), // input
.out_vld (out_vld ), // output
.remain_data (remain_data[4 : 0] ), // output
.div_data (div_data[9 : 0] ) // output
);
initial
begin
clk_r = 0;
in_vld_r = 0;
rst_n_r = 1;
#10
rst_n_r = 0;
#10
rst_n_r = 1;
#10
in_vld_r = 1;
a_data_r = 10'd57;
b_data_r = 5'd8;
#10
in_vld_r = 0;
$finish;
end
always #5 clk_r = !clk_r;
endmodule
測試結果如圖所示:
文章來源:http://www.zghlxwxcb.cn/news/detail-463586.html
57/8 = 7—1;計算正確;文章來源地址http://www.zghlxwxcb.cn/news/detail-463586.html
到了這里,關于verilog實現(xiàn)除法器運算的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!