由于在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;和我们的仿真值比较接近;
只要输入的数据为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即可。
首先计算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];
仿真

·设计思路:
首先计算ρ×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];
·设计代码和仿真

·设计思路:
需要计算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];
·设计代码和仿真

·设计思路:
首先计算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];
·设计代码和仿真

·设计思路:
首先计算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