【【迭代16次的CORDIC算法-verilog实现】】

发布时间:2023年12月21日

迭代16次的CORDIC算法-verilog实现 -32位迭代16次verilog代码实现

CORDIC.v

module cordic32#(
    parameter         DATA_WIDTH    =      8'd32  ,     // we set data width
    parameter         PIPELINE      =      5'd16        // Optimize waveform
  )(
    input                              clk       ,
    input                              rst_n     ,
    input    signed    [DATA_WIDTH - 1 : 0]   phase     ,
    input                              ena       ,
    output  reg signed [DATA_WIDTH - 1  : 0]   sin_out   ,
    output  reg signed [DATA_WIDTH - 1  : 0]   cos_out
  );


  // -----------------------------------------------  \\
  //    next is define and parameter                  \\
  // ------------------------------------------------- \\


  reg    signed     [DATA_WIDTH - 1 : 0]     phase_reg    ;
  reg    signed     [DATA_WIDTH - 1 : 0]     phase_reg1    ;
  reg    signed     [DATA_WIDTH - 1 : 0]     X0           ;
  reg    signed     [DATA_WIDTH - 1 : 0]     Y0           ;
  reg    signed     [DATA_WIDTH - 1 : 0]     Z0           ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X1 , Y1 , Z1 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X2 , Y2 , Z2 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X3 , Y3 , Z3 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X4 , Y4 , Z4 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X5 , Y5 , Z5 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X6 , Y6 , Z6 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X7 , Y7 , Z7 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X8 , Y8 , Z8 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X9 , Y9 , Z9 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X10 , Y10 , Z10 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X11 , Y11 , Z11 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X12 , Y12 , Z12 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X13 , Y13 , Z13 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X14 , Y14 , Z14 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X15 , Y15 , Z15 ;
  wire   signed     [DATA_WIDTH - 1 : 0]     X16 , Y16 , Z16 ;
  reg    signed     [DATA_WIDTH - 1 : 0]     XN15 , YN15     ;





    reg [1:0] quadrant[PIPELINE : 0] ;
    integer i ;











  // We will convert all new angles to the first quadrant
  //
  always@(posedge clk or negedge rst_n)
  begin
    if( rst_n == 0 )
    begin
      phase_reg <= 0 ;
      phase_reg1 <= 0 ;
    end
    else if( ena == 1)
    begin
      phase_reg1 <= phase ;
      case(phase[DATA_WIDTH - 1 : DATA_WIDTH - 2])
        2'b00 :
          phase_reg <= phase                 ;
        2'b01 :
          phase_reg <= phase - 32'h40000000  ;   // -90
        2'b10 :
          phase_reg <= phase - 32'h80000000  ;   // -180
        2'b11 :
          phase_reg <= phase - 32'hC0000000  ;   // -270
        default :
        phase_reg <= 32'h00   ; 
          
      endcase
    end
  end



  // We begin the initialization operation
  // we set 0.607253*???2^31-1???,32'h4DBA775F
  always@(posedge clk or negedge rst_n)
  begin
    if(rst_n == 0 )
    begin
      X0 <= 0 ;
      Y0 <= 0 ;
      Z0 <= 0 ;
    end
    else if(ena == 1)
    begin
      X0 <= 32'h4DBA775F ;
      Y0 <= 0            ;
      Z0 <= phase_reg    ;
    end
  end



// for instantiation - 16
INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd0 ),
    .ANGLE      ( 32'h20000000 )
)u_INTERATION0(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X0         ),
    .Y0         ( Y0         ),
    .Z0         ( Z0         ),
    .X1         ( X1         ),
    .Y1         ( Y1         ),
    .Z1         ( Z1         )
);



INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd1 ),
    .ANGLE      ( 32'h12E4051D )
)u_INTERATION1(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X1         ),
    .Y0         ( Y1         ),
    .Z0         ( Z1         ),
    .X1         ( X2         ),
    .Y1         ( Y2         ),
    .Z1         ( Z2         )
);

INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd2 ),
    .ANGLE      ( 32'h09FB385B )
)u_INTERATION2(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X2         ),
    .Y0         ( Y2         ),
    .Z0         ( Z2         ),
    .X1         ( X3         ),
    .Y1         ( Y3         ),
    .Z1         ( Z3         )
);

INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd3 ),
    .ANGLE      ( 32'h051111D4 )
)u_INTERATION3(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X3         ),
    .Y0         ( Y3         ),
    .Z0         ( Z3         ),
    .X1         ( X4         ),
    .Y1         ( Y4         ),
    .Z1         ( Z4         )
);


INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd4 ),
    .ANGLE      ( 32'h028B0D43 )
)u_INTERATION4(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X4         ),
    .Y0         ( Y4         ),
    .Z0         ( Z4         ),
    .X1         ( X5         ),
    .Y1         ( Y5         ),
    .Z1         ( Z5         )
);


INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd5 ),
    .ANGLE      ( 32'h0145D7E1 )
)u_INTERATION5(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X5         ),
    .Y0         ( Y5         ),
    .Z0         ( Z5         ),
    .X1         ( X6         ),
    .Y1         ( Y6         ),
    .Z1         ( Z6         )
);

INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd6 ),
    .ANGLE      ( 32'h00A2F61E )
)u_INTERATION6(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X6         ),
    .Y0         ( Y6         ),
    .Z0         ( Z6         ),
    .X1         ( X7         ),
    .Y1         ( Y7         ),
    .Z1         ( Z7         )
);



INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd7 ),
    .ANGLE      ( 32'h00517C55 )
)u_INTERATION7(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X7         ),
    .Y0         ( Y7         ),
    .Z0         ( Z7         ),
    .X1         ( X8         ),
    .Y1         ( Y8         ),
    .Z1         ( Z8         )
);

INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd8 ),
    .ANGLE      ( 32'h0028BE53 )
)u_INTERATION8(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X8         ),
    .Y0         ( Y8         ),
    .Z0         ( Z8         ),
    .X1         ( X9         ),
    .Y1         ( Y9         ),
    .Z1         ( Z9         )
);


INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd9 ),
    .ANGLE      ( 32'h00145F2F )
)u_INTERATION9(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X9         ),
    .Y0         ( Y9         ),
    .Z0         ( Z9         ),
    .X1         ( X10         ),
    .Y1         ( Y10         ),
    .Z1         ( Z10         )
);


INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd10 ),
    .ANGLE      ( 32'h000A2F98 )
)u_INTERATION10(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X10         ),
    .Y0         ( Y10         ),
    .Z0         ( Z10         ),
    .X1         ( X11         ),
    .Y1         ( Y11         ),
    .Z1         ( Z11         )
);

INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd11 ),
    .ANGLE      ( 32'h000517CC )
)u_INTERATION11(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X11         ),
    .Y0         ( Y11         ),
    .Z0         ( Z11         ),
    .X1         ( X12         ),
    .Y1         ( Y12         ),
    .Z1         ( Z12         )
);

INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd12 ),
    .ANGLE      ( 32'h00028BE6 )
)u_INTERATION12(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X12         ),
    .Y0         ( Y12         ),
    .Z0         ( Z12         ),
    .X1         ( X13         ),
    .Y1         ( Y13         ),
    .Z1         ( Z13         )
);

INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd13 ),
    .ANGLE      ( 32'h000145F3 )
)u_INTERATION13(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X13         ),
    .Y0         ( Y13         ),
    .Z0         ( Z13         ),
    .X1         ( X14         ),
    .Y1         ( Y14         ),
    .Z1         ( Z14         )
);

INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd14 ),
    .ANGLE      ( 32'h0000A2FA )
)u_INTERATION14(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X14         ),
    .Y0         ( Y14         ),
    .Z0         ( Z14         ),
    .X1         ( X15         ),
    .Y1         ( Y15         ),
    .Z1         ( Z15         )
);


INTERATION#(
    .DATA_WIDTH ( 8'd32 ),
    .shift      ( 5'd15 ),
    .ANGLE      ( 32'h0000517D )
)u_INTERATION15(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .ena        ( ena        ),
    .X0         ( X15         ),
    .Y0         ( Y15         ),
    .Z0         ( Z15         ),
    .X1         ( X16         ),
    .Y1         ( Y16         ),
    .Z1         ( Z16         )
);



// iteration over 


always@(posedge clk or negedge rst_n)
begin
  if(rst_n == 0)
    for(i = 0 ; i < PIPELINE ; i=i+1)
      quadrant[i] <= 0 ;
  else
    if(ena == 1)
    begin
      for(i = 0 ; i < PIPELINE ; i=i+1)
        quadrant[i+1] <= quadrant[i] ;
      quadrant[0] <= phase_reg1[DATA_WIDTH - 1 : DATA_WIDTH - 2] ;
    end
end
 //------------------------------------------  \\
 //------------------------------------------  \\
//  Prevent overflow caused by small decimals and negative complement
//
	
always @(posedge clk or negedge rst_n)
     if(rst_n == 0)
		XN15<=0;
	else if(X15[31:30] == 2'b11)//小于0
		XN15<=~X15 + 1'b1;
	else if(X15[31:30] == 2'b10)//大于1
		XN15<=32'h80000000 - X15 + 32'h80000000;
	else 
		XN15 <= X15;
		
always @(posedge clk or negedge rst_n )
     if(rst_n == 0)
		YN15 <=0;
	else if(Y15[31:30] == 2'b11)//小于0 
		YN15 <=~Y15 + 1'b1;
	else if(Y15[31:30] == 2'b10)//大于1
		YN15 <=32'h80000000 -Y15 + 32'h80000000;
	else 
		YN15 <=Y15;

// 
//   The results of different phases are also different
  //   phase[DATA_WIDTH -1 : DATA_WIDTH -2]
  //  00 first  quadrant
  //  01 second quadrant
  //  10 third  quadrant
  //  11 Fourth Quadrant



always@(posedge clk or negedge rst_n)
begin
  if(rst_n == 0)
  begin
    cos_out <= 0 ;
    sin_out <= 0 ;
  end
  else if( ena == 1)
  begin
    case(quadrant[16]) 
      2'b00 :
      begin
        cos_out <= XN15 ;
        sin_out <= YN15 ;
      end
      2'b01 :
      begin
        cos_out <= ~YN15 + 1'b1;
        sin_out <= XN15        ;
      end
      2'b10 :
      begin
        cos_out <= ~XN15 + 1'b1  ;
        sin_out <= ~YN15 + 1'b1 ;
      end
      2'b11 :
      begin
        cos_out <= YN15        ;
        sin_out <= ~XN15 + 1'b1 ;
      end
    
    endcase
  end
end
endmodule

ITERATION.v

module INTERATION #(
    parameter   DATA_WIDTH       =    8'd32       ,
    parameter   shift            =    5'd0        ,
    parameter   ANGLE            =    32'h20000000
  )(
    input                                  clk     ,
    input                                  rst_n   ,
    input                                  ena     ,
    input       signed  [DATA_WIDTH - 1 : 0]      X0      ,
    input       signed  [DATA_WIDTH - 1 : 0]      Y0      ,
    input       signed  [DATA_WIDTH - 1 : 0]      Z0      ,
    output  reg signed  [DATA_WIDTH - 1 : 0]      X1      ,
    output  reg signed  [DATA_WIDTH - 1 : 0]      Y1      ,
    output  reg signed  [DATA_WIDTH - 1 : 0]      Z1
  );

  always@(posedge clk or negedge rst_n)
  begin
    if( rst_n == 0)
    begin
      X1 <= 0 ;
      Y1 <= 0 ;
      Z1 <= 0 ;
    end
    else if( ena == 1)
    begin
      if(Z0[DATA_WIDTH - 1] == 0 )
      begin
       // X1 <= X0 - {{shift{ Y0[DATA_WIDTH - 1] }} ,Y0[DATA_WIDTH - 1 : shift] } ;
       // Y1 <= Y0 + {{shift{ X0[DATA_WIDTH - 1] }} ,X0[DATA_WIDTH - 1 : shift] } ;
        X1 <= X0 - (Y0>>>shift);
        Y1 <= Y0 + (X0>>>shift);
        Z1 <= Z0 - ANGLE                                                    ;
      end
      else if(Z0[DATA_WIDTH - 1] == 1 )
      begin
        //X1 <= X0 + {{shift{ Y0[DATA_WIDTH - 1 ] }} ,Y0[DATA_WIDTH - 1 : shift] } ;
       // Y1 <= Y0 - {{shift{ X0[DATA_WIDTH - 1 ] }} ,X0[DATA_WIDTH - 1 : shift] } ;
        X1 <= X0 + (Y0>>>shift) ;
        Y1 <= Y0 - {X0>>>shift} ;
        Z1 <= Z0 + ANGLE                                                    ;
      end
    end
  end

endmodule

CORDIC_tb.v

module cordic_tb #(
    parameter         DATA_WIDTH    =      8'd32  ,     // we set data width
    parameter         PIPELINE      =      5'd16        // Optimize waveform    
);
reg                                 clk       ;
reg                                 rst_n     ;
reg          [DATA_WIDTH - 1 : 0]   phase     ;
reg                                 ena       ;
wire         [DATA_WIDTH - 1  : 0]   sin_out   ;
wire         [DATA_WIDTH - 1 : 0]   cos_out   ;



integer i;
cordic32#(
    .DATA_WIDTH ( DATA_WIDTH ),
    .PIPELINE   ( PIPELINE )
)u_cordic32(
    .clk        ( clk        ),
    .rst_n      ( rst_n      ),
    .phase      ( phase      ),
    .ena        ( ena        ),
    .sin_out    ( sin_out    ),
    .cos_out    ( cos_out    )
);


initial
begin
     #0 clk = 1'b0;
    ena   = 1'b1 ;
   
    #10 rst_n = 1'b0;
    #10 rst_n = 1'b1;
    
    #20000000 $stop;
end 

initial
begin
	repeat(10)
	begin
		#0 phase = 32'd0;
		for(i=0;i<131072;i=i+1)
			begin
				#10;
				phase <= phase + 32'h8000;
			end
	end
end
always #10
begin
    clk = ~clk;
end


endmodule 

README.md

在完成CORDIC的7次迭代之后 我在思考一个问题 8位进行了7次迭代 最后迭代至0号称没有误差了
我们是否可以通过 扩展至32位 进行多次迭代  将误差不断的缩小 


本次数据参考至 网上的其他教程 我并没有自己去计算 我把结构优化一下 修改成更加便于理解使用的形式

还有一件事 是 进制 与 Π 转化的问题 
对于 8位 其实我们 一开始将Π 设定为 1000_0000
那么对于 Π/4 是否就是1000_0000 的 四分之一 对于二进制 其实就是整体的数字进行移位 
我们将1000_0000 移动至 0010_0000 于此 

而对于 32位我们32'h8000000 就是一个Π
而 32’h2000_0000 就是四分之Π 


还有一件事 说明 我在写例化的时候 将数据完全完整的例化了下来 写的很长 这样并不是很好 
后面学习中 我看别人是 这么处理的 
genvar die;
generate
    for (die = 0; die <Pipeline; die=die+1)
    begin: dieLoop
        always @(posedge CLK_SYS or negedge RST_N)
            if (!RST_N) begin
                xn[die+1] <= 32'h0;
				yn[die+1] <= 32'h0;
				zn[die+1] <= 32'h0;
            end
        	else begin             
				if(zn[die][31]==1'b0)//角度符号判断
					begin
				     xn[die+1] <= xn[die] - (yn[die]>>>die);
				     yn[die+1] <= yn[die] + (xn[die]>>>die);
				     zn[die+1] <= zn[die] - rot[die];  
				    end
				else begin
				      xn[die+1] <= xn[die] + (yn[die]>>>die);
				      yn[die+1] <= yn[die] - (xn[die]>>>die);
				      zn[die+1] <= zn[die] + rot[die];  
				      end
            end
    end
endgenerate


# 还有一件事 对于溢出的考量 
我们所作溢出的考量 其实我们设定了32'h8000_0000 这既是Π的值 也是 1的设定 
但是在实际的运用和计算中 我们其实永远也达不到1 嘿嘿 
因为我们把最高位设计成了 符号位 
那么最大 也就是1 我们约等于 32'h7fff_ffff
这里需要注意的是[31:28] 是 7 也就是0111 非常重要的一个结论 我们最高位0代表了符号位
那么对于设计到第一象限的[31:30] 的值可以取 00 01 但是 10 11我们要对其进行合适的转化
所以便有了我们  对溢出的操作 


always @(posedge clk or negedge rst_n)
     if(rst_n == 0)
		XN15<=0;
	else if(X15[31:30] == 2'b11)//小于0
		XN15<=~X15 + 1'b1;
	else if(X15[31:30] == 2'b10)//大于1
		XN15<=32'h80000000 - X15 + 32'h80000000;
	else 
		XN15 <= X15;
		
always @(posedge clk or negedge rst_n )
     if(rst_n == 0)
		YN15 <=0;
	else if(Y15[31:30] == 2'b11)//小于0 
		YN15 <=~Y15 + 1'b1;
	else if(Y15[31:30] == 2'b10)//大于1
		YN15 <=32'h80000000 -Y15 + 32'h80000000;
	else 
		YN15 <=Y15;



注意在设计的时候 定义成reg signed 的形式 将其设计为有符号位 

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

文章来源:https://blog.csdn.net/weixin_50965981/article/details/135138759
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。