【FPGA数学公式】使用FPGA实现常用数学公式

218 篇文章 52 订阅
本文详细介绍了如何在FPGA中利用IP核进行串行数据的除法、平均值计算,并通过实例展示了多个公式(如C=368.886%,C=[Σ(A1×B1)/(4×D1)]%,C=(Z2-Z3)/Z2×100%等)的实现过程,涉及除法IP核、存储器操作和数据聚合算法。
摘要由CSDN通过智能技术生成

公式1:

C=Z1/30

       由于在FPGA中进行的数据输入是串行的输入,我们需要做这么一个操作,即将输入的数据存入存储器中,然后每输入一个数据,按一个确定,说明数据已经输入,然后将数据存入存储器中,最后将输入的三十个数据从存储器中读取,然后求平均即可。

    由于除以30不是2的幂次方,所以除以30需要做以下的操作。即通过查找的方法将值从ROM中读取,然后实现除以30的操作。或者使用除法IP核,本系统我们采用的方法是除法IP核的方法来实现除以30的算法。

always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
	  sums       <= 20'd0;
	  
     sums1      <= 20'd0;
     sums2      <= 20'd0;
     sums3      <= 20'd0;
     sums4      <= 20'd0;
     sums5      <= 20'd0;
     sums6      <= 20'd0;
     sums7      <= 20'd0;
     sums8      <= 20'd0;
     sums9      <= 20'd0;
     sums10     <= 20'd0;
     sums11     <= 20'd0;
     sums12     <= 20'd0;
     sums13     <= 20'd0;
     sums14     <= 20'd0;
     sums15     <= 20'd0;
     sums16     <= 20'd0;

     sumst1     <= 20'd0;
     sumst2     <= 20'd0;
     sumst3     <= 20'd0;
     sumst4     <= 20'd0;
     sumst5     <= 20'd0;
     sumst6     <= 20'd0;
     sumst7     <= 20'd0;
     sumst8     <= 20'd0;
 
     sumstt1    <= 20'd0;
     sumstt2    <= 20'd0;
     sumstt3    <= 20'd0;
     sumstt4    <= 20'd0;

     sumsttt1   <= 20'd0;
     sumsttt2   <= 20'd0;	  
	  end
else begin
     sums1      <= i_data1  + i_data2;
     sums2      <= i_data3  + i_data4;
     sums3      <= i_data5  + i_data6;
     sums4      <= i_data7  + i_data8;
     sums5      <= i_data9  + i_data10;
     sums6      <= i_data11 + i_data12;
     sums7      <= i_data13 + i_data14;
     sums8      <= i_data15 + i_data16;
     sums9      <= i_data17 + i_data18;
     sums10     <= i_data19 + i_data20;
     sums11     <= i_data21 + i_data22;
     sums12     <= i_data23 + i_data24;
     sums13     <= i_data25 + i_data26;
     sums14     <= i_data27 + i_data28;
     sums15     <= i_data29;
     sums16     <= i_data30;

     sumst1     <= sums1    + sums2;
     sumst2     <= sums3    + sums4;
     sumst3     <= sums5    + sums6;
     sumst4     <= sums7    + sums8;
     sumst5     <= sums9    + sums10;
     sumst6     <= sums11   + sums12;
     sumst7     <= sums13   + sums14;
     sumst8     <= sums15   + sums16;
 
     sumstt1    <= sumst1   + sumst2;
     sumstt2    <= sumst3   + sumst4;
     sumstt3    <= sumst5   + sumst6;
     sumstt4    <= sumst7   + sumst8;

     sumsttt1   <= sumstt1  + sumstt2;
     sumsttt2   <= sumstt3  + sumstt4;     
	  sums       <= sumsttt1 + sumsttt2;
     end
end


divider divider_u(
						.clk        (i_clk),
						.dividend   (sums),
						.divisor    (16'd30),
						.quotient   (o_average),
						.remainder  (),
						.rfd        ()
						);

除法采用IP核实现;其仿真如下所示:

其标准的运算值为:

368.886;和我们的仿真值比较接近;

公式2:

C=[Σ(A1×B1)/(4×D1)] ×100%

只要输入的数据为A1,B1,D1,然后通过乘法IP核和除法IP核实现公式的运算结果;

实现步骤为:

公式1:A1×B1

公式2:4×D1

公式3:[Σ(A1×B1)/(4×D1)]

公式4:1000*C。得到的结果为%0。

always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
     r1 <= 22'd0;
     r2 <= 32'd0;
	  
     r3 <= 32'd0;
     r4 <= 32'd0;	  
	  end
else begin
     r1 <= i_A1   * i_B1;
     r2 <= 10'd1000 * r1;
	  
     r3 <= 16'd4  * i_D1;
     r4 <= r3;	 
     end
end


divider2 divider2_u(
						 .clk        (i_clk),
						 .dividend   (r2),
						 .divisor    (r4),
						 .quotient   (o_C),
						 .remainder  (),
						 .rfd        ()
						 );

其仿真结果如下所示:

这里为了计算的精度,我们选择的是千分之一的单位,所以最后的结果C为千分之XX。换算为%只要将结果除以10即可。

公式3:

C4=(Z2-Z3)/Z2×100%

    首先计算Z2-Z3;

    然后计算(Z2-Z3)/Z2;

然后使用除法IP核计算其结果,则可以得到其除法结果如下所示:

    由于这里我们对重量的称取是30个一起称的,所以只要记录30个的总量,然后记录三次,然后计算其中的平均值,则可作为贮藏前的总量值以及计算贮藏后的重量值。

    所以在FPGA中输入的时候,我们需要计算的值需要输入3次,然后在FPGA中对输入的三个值计算其中的平均值。然后得到所要的结果。

always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
	  sum1 <= 16'd0;
	  sum2 <= 16'd0;
	  end
else begin
	  sum1 <= i_Z2_1 +i_Z2_2 + i_Z2_3;
	  sum2 <= i_Z3_1 +i_Z3_2 + i_Z3_3;
     end
end

divider3_1 divider3_1_u1(
								.clk        (i_clk),
								.dividend   (sum1),
								.divisor    (16'd3),
								.quotient   (o_Z2_average),
								.remainder  (),
								.rfd        ()
							   );

divider3_1 divider3_1_u2(
								.clk        (i_clk),
								.dividend   (sum2),
								.divisor    (16'd3),
								.quotient   (o_Z3_average),
								.remainder  (),
								.rfd        ()
							   );
								
reg[31:0]r_Z2_average1;
reg[31:0]r_Z2_average2;		
						
reg[15:0]r_Z2_averaget1;
reg[15:0]r_Z2_averaget2;		
							
always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
     r_Z2_average1  <= 32'd0;
     r_Z2_average2  <= 32'd0;	
     r_Z2_averaget1 <= 16'd0;
     r_Z2_averaget2 <= 16'd0;		  
	  end
else begin
     r_Z2_averaget1 <= o_Z2_average - o_Z3_average;
     r_Z2_averaget2 <= o_Z2_average;  

     r_Z2_average1  <= 16'd1000 * r_Z2_averaget1;
     r_Z2_average2  <= {16'b0000_0000_0000_0000,r_Z2_averaget2};		  
     end
end								
								
divider3_2 divider3_2_u(
							  .clk        (i_clk),
							  .dividend   (r_Z2_average1),
							  .divisor    (r_Z2_average2),
							  .quotient   (w_C4),
							  .remainder  (),
							  .rfd        ()
							  );
							  
assign o_C4 = w_C4[15:0];

仿真

公式4:

C=ρV×100/m

·设计思路:

    首先计算ρ×V

    然后计算100×ρ×V

    最后计算100×ρ×V/m;

always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
     pv    <=22'd0;
     pv100 <=32'd0;
     m1    <=32'd0;
     m2    <=32'd0;	  
	  end
else begin
     pv    <=  i_P    * i_V;
     pv100 <=  10'd1000 * pv;
     m1    <= {16'b0000_0000_0000_0000,i_m};
     m2    <=  m1;    
     end
end

divider5 divider5_u(
						 .clk        (i_clk),
						 .dividend   (pv100),
						 .divisor    (m2),
						 .quotient   (w_C),
						 .remainder  (),
						 .rfd        ()
						 );

assign o_C = w_C[15:0];

·设计代码和仿真

   

公式5:

C=44×(V1-V2) ×M / (W×h)

·设计思路:

    需要计算V1-V2;

    然后计算44*(V1-V2)

    然后计算44*(V1-V2)*M

    然后计算W*h

    最后计算44*(V1-V2)*M/(W*h)


always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
     r_V <= 16'd0;
     r_V1<= 26'd0;
     r_V2<= 32'd0;
     wh1 <= 32'd0;
     wh2 <= 32'd0;
     wh3 <= 32'd0;	  
	  end
else begin
     r_V <= i_V1 - i_V2;
     r_V1<= r_V  * i_M;
     r_V2<= 6'd44* r_V1;
	  
     wh1 <= i_W  * i_h;
     wh2 <= wh1;
	  wh3 <= wh2;
     end
end
						  
divider5 divider5_u(
						 .clk        (i_clk),
						 .dividend   (r_V2),
						 .divisor    (wh3),
						 .quotient   (w_C),
						 .remainder  (),
						 .rfd        ()
						 );

assign o_C = w_C[15:0];

·设计代码和仿真

公式6:

C=0.88 / (V1-V2)

·设计思路:

    首先计算V1-V0

    然后计算88*(V1-V0)

    最后计算88*(V1-V0)/100

always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
     r_V <= 16'd0;
     r_V1<= 32'd0;
	  end
else begin
     r_V <= i_V1   - i_V0;
     r_V1<= 16'd88 * r_V;
     end
end
wire[31:0]w_C;
divider5 divider5_u(
						 .clk        (i_clk),
						 .dividend   (r_V1),
						 .divisor    (32'd100),
						 .quotient   (w_C),
						 .remainder  (),
						 .rfd        ()
						 );

assign o_C = w_C[15:0];

·设计代码和仿真

公式7:

C=(c×V1×V2×100)/(V0×m)

·设计思路:

     首先计算c*V1

     然后计算c*V1*V2

     然后计算100* c*V1*V2

     然后计算V0×m

     最后计算(100* c*V1*V2)/(V0×m);

always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
     r1 <= 16'd0;
     r2 <= 16'd0;
     r3 <= 32'd0;	 

     r4 <= 32'd0;	 
     r5 <= 32'd0;
     r6 <= 32'd0;	  
	  end
else begin
     r1 <= 8'd100 * i_V1;
     r2 <= i_V2   * i_c;
     r3 <= r1     * r2;	 

     r4 <= i_V0 * i_m;	 
     r5 <= r4;	     
	  r6 <= r5;
     end
end

wire[31:0]w_C;
divider5 divider5_u(
						 .clk        (i_clk),
						 .dividend   (r3),
						 .divisor    (r6),
						 .quotient   (w_C),
						 .remainder  (),
						 .rfd        ()
						 );

assign o_C = w_C[15:0];

·设计代码和仿真

A16-34
 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fpga和matlab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值