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 ,利用移位实现;
对应时序:

对应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
仿真结果:

即-40/200 = 0.2 ,仿真结果为:-205/1024(2^10) = -0.2002,仿真正确。
module delay:LOOPS = 15 clk.
原文:https://www.cnblogs.com/mia1004/p/11626879.html