FPGA流水线除法器(Verilog)原理及实现

FPGA流水线除法器(Verilog)原理及实现

流水线除法器原理

  除法器的计算过程如下图所示。
FPGA流水线除法器(Verilog)原理及实现_第1张图片

计算步骤

假设数值的位宽为N。
Step1:分别将被除数和除数扩展至原来2倍位宽(2N),被除数在其左边补N位0,除数在其右边补N位0;
Step2:将被除数依次左移(每次左移1位),末位补数值(该数值为被除数高N位与除数高N位的商),高N位为被除数高N位与除数高N位的余数。移位执行N次,执行N次后,进入Step3;
Step3:此时被除数的低N位为计算得到的商,被除数的高N位为计算得到的余数。

流水线除法器Verilog代码

module pipeline_divider
#(
	parameter		N = 8
)
(
	input					clk		,	//时钟信号
	input					rst_n	,	//复位信号
	input					start	,	//开始信号
	input		[N-1:0]		dividend,	//被除数
	input		[N-1:0]		divisor	,	//除数
	
	output		[N-1:0]		quotient	,	//商
	output		[N-1:0]		remainder	,	//余数
	output					finish			//计算结束信号
);

//============================================
//                  变量声明
//============================================

//------------------内部变量------------------
reg		[2*N-1:0]		dividend_temp ;
reg		[2*N-1:0]		divisor_temp;
reg						finish_temp;
reg						state;
reg		[$clog2(N):0]	cnt;

//-----------------状态机状态-----------------
parameter	Init = 'd0;
parameter	Calc = 'd1;

//============================================
//                流水线除法器
//============================================

always @(posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		dividend_temp <= 0;
		divisor_temp <= 0;
		finish_temp <= 0;
		cnt <= 0;
		state <= Init;
	end
	else begin
		case(state)
			Init:
				begin
					if(start) begin
						cnt <= 0;
						finish_temp <= 0;
						dividend_temp <= {{N{1'b0}},dividend};
						divisor_temp <= {divisor,{N{1'b0}}};
						state <= Calc;
					end
				end
			Calc:
				begin
					if(cnt == N) begin
						finish_temp <= 1'b1;
						state <= Init;
					end
					else begin
						if(dividend_temp[2*N-2:N-1] >= divisor_temp[2*N-1:N]) begin
							dividend_temp <= {dividend_temp[2*N-2:0],1'b0} - divisor_temp + 1'b1;
						end
						else begin
							dividend_temp <= {dividend_temp[2*N-2:0],1'b0};
						end
						cnt <= cnt + 1'b1;
					end
				end
		endcase
	end
	
end

//============================================
//                	模块输出
//============================================
assign	finish = finish_temp;	
assign	quotient = finish ? dividend_temp[N-1:0] : 0;
assign	remainder = finish ? dividend_temp[2*N-1:N] : 0;


endmodule

Test_Bench

   这里简单的写个测试文件对流水线除法器进行功能测试,判断是否符合预期的计算结果。

`timescale 1ns/1ps
module tb_pipeline_divider();

parameter		N = 8;
reg		clk,rst_n,start;
reg		[N-1:0]		dividend;	//被除数
reg		[N-1:0]		divisor	;	//除数
wire	[N-1:0]		quotient;
wire	[N-1:0]		remainder;
wire				finish;

initial begin
	clk = 1'b0;
	rst_n = 1'b0;
	start = 1'b0;
	dividend = 'd23;
	divisor = 'd3;
	#20
	rst_n = 1'b1;
	
	#100
	start = 1'b1;

end


always #10 clk = ~clk;

pipeline_divider
#(
	.N(N)
)
pipeline_divider_inst
(
	.clk		(clk		),	//时钟信号
	.rst_n		(rst_n		),	//复位信号
	.start		(start		),	//开始信号
	.dividend	(dividend	),	//被除数
	.divisor	(divisor	),	//除数
	
	.quotient	(quotient	),	//商
	.remainder	(remainder	),	//余数
	.finish     (finish     )	//结束信号
);

endmodule

仿真结果

FPGA流水线除法器(Verilog)原理及实现_第2张图片
  这里被除数为23,除数为3,得到商为7,余数为2,仿真所得计算结果正确,验证通过。

注:本博客仅为个人学习笔记,如有错误之处,请指正,如有转载请备注出处,谢谢。

你可能感兴趣的:(FPGA学习,fpga开发)