开平方的verilog代码

目录

1.逐次逼近算法描述

2.Verilog实现

 3.Testbench编写


1.逐次逼近算法描述

        逐次逼近算法流程如图 1所示,首先数据输入data[7:0],接着设置实验值D_z[3:0]和确定值D_q[3:0],然后按照从高往低的顺序,依次将每一位置1(如D_z[3]置1),再将实验值平方后与输入数据比较,若实验值的平方大于输入值(D_z^2 > data),则此位为0(D_q[3]为0),反之((D_z^2 ≤ data)),此位为1(D_q[3]为1);以此迭代到最后一位。

可见,如果是n bit的数据,那么需要n/2次迭代,每次计算如果一个周期,则需要n/2个周期。

 

开平方的verilog代码_第1张图片

                                                                                    图 1逐次逼近算法框图

2.Verilog实现


   
   
   
   
  1. //////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // 逐次逼近算法
  4. //
  5. module sqrt_1
  6. #(
  7. parameter d_width = 8,
  8. parameter q_width = d_width/2 - 1,
  9. parameter r_width = q_width + 1 )
  10. (
  11. input wire clk,
  12. input wire rst,
  13. input wire i_vaild,
  14. input wire [d_width:0] data_i, //输入
  15. output reg o_vaild,
  16. output reg [q_width:0] data_o, //输出
  17. output reg [r_width:0] data_r //余数
  18. );
  19. //--------------------------------------------------------------------------------
  20. reg [d_width:0] D [r_width:1]; //被开方数
  21. reg [q_width:0] Q_z [r_width:1]; //临时
  22. reg [q_width:0] Q_q [r_width:1]; //确认
  23. reg ivalid_t [r_width:1];
  24. //--------------------------------------------------------------------------------
  25. always@(posedge clk or posedge rst)
  26. begin
  27. if(rst)
  28. begin
  29. D[r_width] <= 0;
  30. Q_z[r_width] <= 0;
  31. Q_q[r_width] <= 0;
  32. ivalid_t[r_width] <= 0;
  33. end
  34. else if(i_vaild)
  35. begin
  36. D[r_width] <= data_i; //被开方数据
  37. Q_z[r_width] <= {1'b1,{q_width{1'b0}}}; //实验值设置
  38. Q_q[r_width] <= 0; //实际计算结果
  39. ivalid_t[r_width] <= 1;
  40. end
  41. else
  42. begin
  43. D[r_width] <= 0;
  44. Q_z[r_width] <= 0;
  45. Q_q[r_width] <= 0;
  46. ivalid_t[r_width] <= 0;
  47. end
  48. end
  49. //-------------------------------------------------------------------------------
  50. // 迭代计算过程
  51. //-------------------------------------------------------------------------------
  52. generate
  53. genvar i;
  54. for(i=r_width-1;i>=1;i=i-1)
  55. begin:U
  56. always@(posedge clk or posedge rst)
  57. begin
  58. if(rst)
  59. begin
  60. D[i] <= 0;
  61. Q_z[ i] <= 0;
  62. Q_q[ i] <= 0;
  63. ivalid_t[ i] <= 0;
  64. end
  65. else if( ivalid_t[ i+ 1])
  66. begin
  67. if( Q_z[ i+ 1]* Q_z[ i+ 1] > D[i+1])
  68. begin
  69. Q_z[i] <= {Q_q[i+1][q_width:i],1'b1,{{i-1}{1'b0}}};
  70. Q_q[i] <= Q_q[i+1];
  71. end
  72. else
  73. begin
  74. Q_z[i] <= {Q_z[i+1][q_width:i],1'b1,{{i-1}{1'b0}}};
  75. Q_q[i] <= Q_z[i+1];
  76. end
  77. D[i] <= D[i+1];
  78. ivalid_t[i] <= 1;
  79. end
  80. else
  81. begin
  82. ivalid_t[i] <= 0;
  83. D[i] <= 0;
  84. Q_q[i] <= 0;
  85. Q_z[i] <= 0;
  86. end
  87. end
  88. end
  89. endgenerate
  90. //--------------------------------------------------------------------------------
  91. // 计算余数与最终平方根
  92. //--------------------------------------------------------------------------------
  93. always@(posedge clk or posedge rst)
  94. begin
  95. if(rst)
  96. begin
  97. data_o <= 0;
  98. data_r <= 0;
  99. o_vaild <= 0;
  100. end
  101. else if(ivalid_t[1])
  102. begin
  103. if(Q_z[1]*Q_z[1] > D[1])
  104. begin
  105. data_o <= Q_q[1];
  106. data_r <= D[1] - Q_q[ 1]* Q_q[ 1];
  107. o_vaild <= 1;
  108. end
  109. else
  110. begin
  111. data_o <= {Q_q[1][q_width:1],Q_z[1][0]};
  112. data_r <= D[1] - { Q_q[ 1][ q_width:1], Q_z[ 1][ 0]}*{ Q_q[ 1][ q_width:1], Q_z[ 1][ 0]};
  113. o_vaild <= 1;
  114. end
  115. end
  116. else
  117. begin
  118. data_o <= 0;
  119. data_r <= 0;
  120. o_vaild <= 0;
  121. end
  122. end
  123. // --------------------------------------------------------------------------------

 3.Testbench编写

 
   
   
   
   
//--------------------------------------------------------------------------------
	`define  		 						d_w 		 8
	`define        						q_w		 `d_w / 2
	`define        						r_w 		 `q_w + 1
//--------------------------------------------------------------------------------
module tb_sqrt;
//--------------------------------------------------------------------------------
	// Inputs
	reg 										clk;
	reg 										rst;
	reg					 					i_vaild;
	reg 			[`d_w-1:0] 				data_i;

	// Outputs
	wire 										o_vaild;
	wire 			[`q_w-1:0]				data_o;
	wire 			[`r_w-1:0]				data_r;

//--------------------------------------------------------------------------------
	// Instantiate the Unit Under Test (UUT)
	sqrt_1 
	#(
		.d_width		( 	`d_w-1		),
		.q_width 	(	`q_w-1		),
		.r_width 	(  `r_w-1		)	
	)
		uut 
	(
		.clk			(	clk			), 
		.rst			(	rst			), 
		.i_vaild		(	i_vaild		), 
		.data_i		(	data_i		), 
		.o_vaild		(	o_vaild		), 
		.data_o		(	data_o		), 
		.data_r		(	data_r		)
	);
//--------------------------------------------------------------------------------
	initial begin
		// Initialize Inputs
		clk = 0;
		rst = 1;
		// Wait 100 ns for global reset to finish
		#100;
      rst = 0; 
		// Add stimulus here

	end
    
	always #5 clk  = ~ clk ;
	
	reg	[`d_w:0]		cnt ;
	
	reg	[31:0]		a ;
//--------------------------------------------------------------------------------
	always@(posedge	clk or posedge	rst)
		begin
			if(rst)
				begin
					i_vaild <= 0;
					data_i <= 0;
					cnt <= 0;
				end
			else	if(cnt < 10)
				begin
					i_vaild <= 1;
					data_i <= {$random} % 255;
					cnt <= cnt + 1;
				end
			else
				begin
					i_vaild <= 0;
					data_i <= 0;
					cnt <= cnt;
				end
		end
//--------------------------------------------------------------------------------
endmodule

 

 

        用语句 data_i <= {$random} % 255; 产生一个0~255的随机数进行测试。

 

 

        仿真结果如图 2所示,计算周期为4个时钟周期,输入数据data_i,开方结果data_o,余数data_r。

                                                                                    图 2 仿真结果

你可能感兴趣的:(FPGA,平方根)