首先定义端口如下,输入位宽参数化,开根号的结果位宽是输入位宽的一半,余数多保留3位。代码在输入数据有效时进行计算,输出开根号的结果和余数。
module cm_sqrt #( parameter C_DATA_WITH_IN = 32 , parameter C_DATA_WITH_OUT = C_DATA_WITH_IN/2 , parameter C_DATA_WITH_REM = C_DATA_WITH_OUT+3 )( input wire I_sys_clk , /// 系统时钟 input wire I_data_en , /// 数据有效标志,与数据对齐 input wire [C_DATA_WITH_IN-1:0] I_data_in , /// 输入数据 output reg O_data_en , /// 数据有效标志,与数据对齐 output reg [C_DATA_WITH_OUT-1:0] O_data_out , /// 开根号的结果 output reg [C_DATA_WITH_REM-1:0] O_data_rem ); /// 余数
根据开根号原理,首先对最高两位进行判断:
如果是1,取高四位减b100,得到余数为差值,同时开根号的结果赋值为1;
如果是0,直接取高四位得到余数,开根号结果为0;
always @(posedge I_sys_clk) if(I_data_en) if(|I_data_in[C_DATA_WITH_IN-1:C_DATA_WITH_IN-2]) /// 高位是1,取高四位减b100,得到余数 begin S_data_out <= {{(C_DATA_WITH_OUT-1){1'b0}},1'b1}; S_data_rem <= {{(C_DATA_WITH_REM-5){1'b0}},I_data_in[C_DATA_WITH_IN-1:C_DATA_WITH_IN-4]}-3'b100; end else /// 高位是0,直接取高四位得到余数 begin S_data_out <= {{(C_DATA_WITH_OUT-1){1'b0}},1'b0}; S_data_rem <= {{(C_DATA_WITH_REM-5){1'b0}},I_data_in[C_DATA_WITH_IN-1:C_DATA_WITH_IN-4]}; end
然后算下一步的余数是否大于(2a+1),其中a是当前开根号的结果*2,
assign S_data_rem_cut = S_data_rem - {1'b0,S_data_out[C_DATA_WITH_OUT-1:0],2'b0} - 1'b1;
如果大于,则开根号的结果为1,新的余数为{差值,输入的下两位},否则开根号的结果为0,新的余数为{当前余数,输入的下两位}。
if(S_data_rem_cut[C_DATA_WITH_REM-1]) /// 判断是否大于 2*a+1 begin S_data_out <= {S_data_out[C_DATA_WITH_OUT-2:0],1'b0}; S_data_rem <= {S_data_rem[C_DATA_WITH_REM-3:0],S_data_in[C_DATA_WITH_IN-5:C_DATA_WITH_IN-6]}; end else begin S_data_out <= {S_data_out[C_DATA_WITH_OUT-2:0],1'b1}; S_data_rem <= {S_data_rem_cut[C_DATA_WITH_REM-3:0],S_data_in[C_DATA_WITH_IN-5:C_DATA_WITH_IN-6]}; end
循环上述操作即可得到最终开根号的结果。
以上文中的例子详细说明图如下:
1、首先判断高两bit大于1,直接将高4bit减去3‘b100,得到余数为b11;
2、然后判断b11是否大于2a+1(此时a为b10),即b11是否大于101,判断结果为小于101;
3、新的余数变为b1101,开根号的结果为10,判断b1101是否大于2a+1(此时a为b100),即b1101是否大于1001,判断结果大于1001,差值为b100;
4、新的余数变为b10010,开根号的结果为101,判断b10010是否大于2a+1(此时a为b1010),即b10010是否大于b10101,判断结果小于。
5、循环结束,开根号的结果为b1010,余数为b10010。
使用随机数仿真如下,输入为随机数,仿真证明代码功能正常:
详细的视频教程见B站视频:【FPGA设计之verilog实现开根号】 https://www.bilibili.com/video/BV1we4y1U7zW/?share_source=copy_web&vd_source=9736f43bc2eebc284f4fbbe5805247a7