FPGA篇(一) 基于verilog的定点开方运算(1)-逐次逼近算法
目錄
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個周期。
?
????????????????????????????????????????????????????????????????????????????????????圖 1逐次逼近算法框圖
2.Verilog實現
// // // 逐次逼近算法 // module sqrt_1#( parameter d_width = 8,parameter q_width = d_width/2 - 1,parameter r_width = q_width + 1 )(input wire clk,input wire rst,input wire i_vaild,input wire [d_width:0] data_i, //輸入output reg o_vaild,output reg [q_width:0] data_o, //輸出output reg [r_width:0] data_r //余數); //--------------------------------------------------------------------------------reg [d_width:0] D [r_width:1]; //被開方數reg [q_width:0] Q_z [r_width:1]; //臨時reg [q_width:0] Q_q [r_width:1]; //確認reg ivalid_t [r_width:1]; //--------------------------------------------------------------------------------always@(posedge clk or posedge rst)beginif(rst)beginD[r_width] <= 0;Q_z[r_width] <= 0;Q_q[r_width] <= 0;ivalid_t[r_width] <= 0;endelse if(i_vaild)beginD[r_width] <= data_i; //被開方數據Q_z[r_width] <= {1'b1,{q_width{1'b0}}}; //實驗值設置Q_q[r_width] <= 0; //實際計算結果ivalid_t[r_width] <= 1;endelsebeginD[r_width] <= 0;Q_z[r_width] <= 0;Q_q[r_width] <= 0;ivalid_t[r_width] <= 0;endend //------------------------------------------------------------------------------- // 迭代計算過程 //-------------------------------------------------------------------------------generategenvar i;for(i=r_width-1;i>=1;i=i-1)begin:Ualways@(posedge clk or posedge rst)beginif(rst)beginD[i] <= 0;Q_z[i] <= 0;Q_q[i] <= 0;ivalid_t[i] <= 0;endelse if(ivalid_t[i+1])beginif(Q_z[i+1]*Q_z[i+1] > D[i+1])beginQ_z[i] <= {Q_q[i+1][q_width:i],1'b1,{{i-1}{1'b0}}};Q_q[i] <= Q_q[i+1];endelsebeginQ_z[i] <= {Q_z[i+1][q_width:i],1'b1,{{i-1}{1'b0}}};Q_q[i] <= Q_z[i+1];endD[i] <= D[i+1];ivalid_t[i] <= 1;endelsebeginivalid_t[i] <= 0;D[i] <= 0;Q_q[i] <= 0;Q_z[i] <= 0;endendendendgenerate //-------------------------------------------------------------------------------- // 計算余數與最終平方根 //--------------------------------------------------------------------------------always@(posedge clk or posedge rst) beginif(rst)begindata_o <= 0;data_r <= 0;o_vaild <= 0;endelse if(ivalid_t[1])beginif(Q_z[1]*Q_z[1] > D[1])begindata_o <= Q_q[1];data_r <= D[1] - Q_q[1]*Q_q[1];o_vaild <= 1;endelsebegindata_o <= {Q_q[1][q_width:1],Q_z[1][0]};data_r <= D[1] - {Q_q[1][q_width:1],Q_z[1][0]}*{Q_q[1][q_width:1],Q_z[1][0]};o_vaild <= 1;endendelsebegindata_o <= 0;data_r <= 0;o_vaild <= 0;endend //--------------------------------------------------------------------------------?3.Testbench編寫
? //--------------------------------------------------------------------------------`define d_w 8`define q_w `d_w / 2`define r_w `q_w + 1 //-------------------------------------------------------------------------------- module tb_sqrt; //--------------------------------------------------------------------------------// Inputsreg clk;reg rst;reg i_vaild;reg [`d_w-1:0] data_i;// Outputswire 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 Inputsclk = 0;rst = 1;// Wait 100 ns for global reset to finish#100;rst = 0; // Add stimulus hereendalways #5 clk = ~ clk ;reg [`d_w:0] cnt ;reg [31:0] a ; //--------------------------------------------------------------------------------always@(posedge clk or posedge rst)beginif(rst)begini_vaild <= 0;data_i <= 0;cnt <= 0;endelse if(cnt < 10)begini_vaild <= 1;data_i <= {$random} % 255;cnt <= cnt + 1;endelsebegini_vaild <= 0;data_i <= 0;cnt <= cnt;endend //-------------------------------------------------------------------------------- endmodule?
?
????????用語句 data_i <= {$random} % 255; 產生一個0~255的隨機數進行測試。
?
?
????????仿真結果如圖 2所示,計算周期為4個時鐘周期,輸入數據data_i,開方結果data_o,余數data_r。
????????????????????????????????????????????????????????????????????????????????????圖 2 仿真結果
總結
以上是生活随笔為你收集整理的FPGA篇(一) 基于verilog的定点开方运算(1)-逐次逼近算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 点滴篇(一) 第一篇 博客
- 下一篇: FPGA篇(三)基于FPGA的几种排序算