001-CORDIC实现除法

2019年10月6日10:07:26

CORDIC除法原理不再赘述:

MATLAB(适用条件:除数不能超过被除数的2倍):

function div_res = cordic_div(frac_up, frac_down, loops)
% INTIAL 
div_res = 0;
value = 1;

% CORDIC
for i = 0:loops - 1
   if((frac_down * frac_up) < 0) 
       x_new = frac_down;
       y_new = (frac_up + frac_down) * 2;
       frac_down = x_new;
       frac_up = y_new;
       div_res = div_res - value * 2 ^-i;
   else
       x_new = frac_down;
       y_new = (frac_up - frac_down) * 2;
       frac_down = x_new;
       frac_up = y_new;
       div_res = div_res + value * 2 ^-i;
   end
end
end 

  

对应FPGA实现思路:

1)初始化对应RST复位实现;

2)(frac_down * frac_up) < 0 用异或实现;

3)迭代利用generate + 寄存器组实现,每一个迭代单元单独例化一个子程序;

4)2^-i,以及 * 2 ,利用移位实现;

对应时序:

001-CORDIC实现除法

对应FPGA代码:

tb

`timescale 1ns / 1ps

module tb;
/************* PARAMETER ******************/
parameter LOOPS = 15;
parameter DATWIDTH = 16;
parameter RESWIDTH = 12;
/**************** INPUT OUTOUT ************/
logic    signed    [DATWIDTH - 1:0]    fracDown;
logic    signed    [DATWIDTH - 1:0]    fracUp;
logic    signed    [RESWIDTH - 1:0]    divRes;
/**************** INITIAL *****************/
logic    clk;
logic    rst;

initial begin
clk = 0;
rst = 1'b1;
fracDown = 0;
fracUp = 0;
#20
rst = 1'b0;
#200
fracDown = 16'd200;
fracUp = -16'd40;

#1000
$stop;
end
always #2 clk = !clk;
/**************** CORDIV ******************/
cordic_div #(
	.LOOPS(LOOPS),
	.DATWIDTH(DATWIDTH),
	.RESWIDTH(RESWIDTH)
)
Ucordic_div(
	.clk(clk), 
	.rst(rst), 
	.fracDown(fracDown), 
	.fracUp(fracUp), 
	.divRes(divRes)
);

glbl glbl();
endmodule

  

cordic_div

module cordic_div(clk, rst, fracDown, fracUp, divRes);
/********** PARAMETER **************/
parameter LOOPS = 15;
parameter DATWIDTH = 16;
parameter RESWIDTH = 12;
/********** INPUT OUTPUT ***********/
input    clk;
input    rst;
input    signed    [DATWIDTH - 1:0]    fracDown;
input    signed    [DATWIDTH - 1:0]    fracUp;

output    wire    signed    [RESWIDTH - 1:0]    divRes;
/********** CORDIC *****************/
// PIPE LINE
wire    signed    [LOOPS:0][DATWIDTH - 1:0]    fracDown1;
wire    signed    [LOOPS:0][DATWIDTH - 1:0]    fracUp1;
wire    signed    [LOOPS:0][RESWIDTH - 1:0]    divRes1;
// INITIAL
assign fracDown1[0] = fracDown;
assign fracUp1[0] = fracUp;
assign divRes1[0] = {RESWIDTH{1'b0}};

genvar ii;
generate 
for (ii = 0; ii < LOOPS; ii = ii + 1)
begin: cordic_ii
	cordiv_unit #(
	.DATWIDTH(DATWIDTH),
	.RESWIDTH(RESWIDTH),
	.STAGE(ii)
	)
	Ucordiv_unit(
	.clk(clk), 
	.rst(rst), 
	.xin(fracDown1[ii]), 
	.yin(fracUp1[ii]), 
	.zin(divRes1[ii]), 
	.xout(fracDown1[ii + 1]), 
	.yout(fracUp1[ii + 1]), 
	.zout(divRes1[ii + 1])
	);
end
endgenerate

assign divRes = divRes1[LOOPS];

endmodule

  

cordiv_unit

module cordiv_unit(clk, rst, xin, yin, zin, xout, yout, zout);
/*************** PARAMETER ********************/
parameter DATWIDTH = 16;
parameter RESWIDTH = 12;
parameter STAGE = 0;
parameter VALUE = 12'h400;
/************** INPUT OUTPUT ******************/
input    clk;
input    rst;
input    signed    [DATWIDTH - 1:0]    xin;
input    signed    [DATWIDTH - 1:0]    yin;
input    signed    [RESWIDTH - 1:0]    zin;

output    reg    signed    [DATWIDTH - 1:0]    xout; 
output    wire    signed    [DATWIDTH - 1:0]    yout; 
output    reg    signed    [RESWIDTH - 1:0]    zout;

/************** CORDIC UINIT *******************/
reg    [DATWIDTH - 1:0]    yout1;

always @(posedge clk) begin
	if(rst) begin
		xout <= {DATWIDTH{1'b0}};
		yout1 <= {DATWIDTH{1'b0}};
		zout <= {RESWIDTH{1'b0}};
	end
	else begin
		xout <= xin;
		if(xin[DATWIDTH - 1]^yin[DATWIDTH - 1]) begin
			yout1 <= yin + xin;
			zout <= zin - (VALUE >> STAGE);
		end
		else  begin
			yout1 <= yin - xin;
			zout <= zin + (VALUE >> STAGE);			
		end
	end
end

assign yout = {yout1[DATWIDTH - 1], yout1[DATWIDTH - 3:0], 1'b0};

endmodule

  

仿真结果:

001-CORDIC实现除法

 

即-40/200 = 0.2 ,仿真结果为:-205/1024(2^10) = -0.2002,仿真正确。

module delay:LOOPS = 15 clk.

 

 

上一篇:002-CORDIC实现幅度相位求解


下一篇:利用Xilinx的cordic ip做开方运算