目标反射回波检测算法及其FPGA实现之二:

互相关/卷积/FIR电路的FPGA实现

前段时间,接触了一个声呐目标反射回波检测的项目。声呐接收机要实现的核心功能是在含有大量噪声的反射回波中,识别出发射机发出的激励信号的回波。我会分几篇文章分享这个基于FPGA的回波识别算法的开发过程和原码,欢迎大家不吝赐教。以下原创内容欢迎网友转载,但请注明出处: https://www.cnblogs.com/helesheng

在本系列博文的第一篇中,根据仿真结果,我认为采用“反射回波和激励信号互相关”来计算目标距离的算法具有较高性能和计算效率。作为系列文章的第二篇,本文将介绍算法的核心功能——互相关的FPGA实现方法。本文会以数据结构的实现方式为主线,综合考虑电路的计算实时性、灵活性和成本效率等方面问题。

要实现的互相关运算在连续域的描述方式为:

                                                          (1)

其中M(t)为激励信号,s(t)为反射回波信号。在FPGA中实现上式时必须将其离散化,并限制在有限的时间长度内。好在激励信号M(t)本来就是有限时长的,对其实施一个满足奈奎斯特采样定理的离散化后【注:作为算法的验证,我们在预备篇中使用了采样率仅为50KSPS的ADC:MCP3202,但这并不妨碍我们验证算法的正确性。实际的声呐系统中采样率可能远超过50KSPS】,可以将上式简化为FPGA能够实现的形式:

其中N为激励信号的长度(采样点数)。

一望便知,上式是数字信号处理的典型计算——乘加(MAC)运算的组合。将激励信号M[t]镜像翻转:

就可以将(2)式变为我们熟悉的卷积算法:

当上式中的h[k[视为系统的冲击响应时,上式还可以理解为更为常见的FIR滤波算法。

由于激励信号一般具有镜像对称性(或称左右对称),即(3)式中翻转前的M[k]和h[k]和完全相同。为了使设计的FPGA电路具有更好的通用性,接下来不妨直接讨论卷积/FIR滤波运算(4)式的实现方式。

一、总体电路结构

中高端FPGA一般集成了硬件MAC电路,如Xilinx公司的DSP48E模块和Altera(Intel)公司的Embedded multipliers模块。这些MAC模块不需要占用FPGA中的通用可编程资源,工作频率可高达大几百MHz,且大大降低开发难度。但声呐系统的采样率一般不会超过10MHz,为了使本算法能够在高、中、低档的各类FPGA上兼容,我选择通过EDA工具提供的MAC的IP核实现算法。验证算法使用的是,不具备硬件MAC模块的,常见低成本FPGA:Cyclone-I系列。

为保证算法的实时性,必须在一个A/D采样周期内实现(4)式中的N个点的乘加运算。最直接的方式是在FPGA中实现N个乘加器,全并行的完成(4)式的计算。但这样做将耗费大量的FPGA资源(Cyclone-I中,每个16*16bits的乘加器约需500个LE资源),且当N确定后电路结构就固定了,不太容易修改。为使设计的电路更具“通用性”和“灵活性”,以兼容更多的激励信号长度N值,我才用下图所示的“半并行”结构实现(4)式的卷积算法。

图1 半并行结构的互相关/卷积/FIR滤波器结构

这相当于将一段长度为N公里的“公路工程”,平均分配给L个“工程队”来实施。在每个工程队同时工作,且效率相同的前提下,工程耗时将降低为原来的1/L;当然L个工程队所需的“工资”也变为原来的L倍。实际使用时,可以根据总工程量N和FPGA的资源情况,灵活的调整L,从而在实时性和电路规模之间取得平衡。以下为方便讨论,且不失一般性,将以N=64,L=4为例讨论。

设计时虽然可以利用Verilog-HDL的泛化能力,将相同的功能模块例化为4个结构相同的“工程队”,以下简称为“卷积节”。在设计功能模块时,必须考虑输入数据s[k]和卷积模板h[k]存储的数据结构。必须满足以下要求:

1、在单个R[n]的计算中,每个卷积节需要遍历数据缓冲区中的所有s[k[数据,以及系数存储器中的所有卷积系数h[k]。

2、在完成一个R[n]的计算后,每个卷积节需要接收前一个卷积节或A/D采样得到的新缓冲数据,同时将缓冲中“最老”的数据传递给下一个卷积节。

我设计了图1所示“双存储器”结构实现上述两条数据结构功能,其物理载体都是Cyclone系列中的M4K存储块(M4K RAM blocks)。图中绿色部分是存储输入数据s[k]的缓冲区,是“简单双端口RAM”。它有两个数据端口:一个负责向缓冲区存入新数据,每个A/D采样周期存入一次;另一个负责读取乘加运算所需的数据,每个A/D采样周期读取16次(即N/L次)。其存取采用“环形队列”数据结构。图中蓝色部分是卷积系数h[k]的存储器,它每个A/D采样周期读取16次,数据不更新。

另外,当互相关/卷积的模板具备对称性时,也就是对应的FIR滤波器具有线性相位的情况下,图1所示的算法电路还能进一步简化,计算量降低为N/2次乘加MAC运算,这里就不讨论了。

二、卷积节控制电路的设计

通过上文的描述,相信读者可以感觉得到:整个卷积电路的重点在每个卷积节的实现,而卷积节实现的关键是能够正确的控制“数据缓冲区”、“系数存储器”和“乘加器(MAC)”的协调工作。其工作内容是在每个A/D采样结果到来,而下一个结果未到之前,完成:

1、产生一个写地址,将A/D结果存入缓冲区最老数据所在位置,同时将最老的数据输出给下一个卷积节;

2、同步产生两组、各16个读地址,分别从数据缓冲区和系数存储器读取一遍其中的所有数据;

3、将顺序读取的两组数据顺序乘加在一起。

实现上述功能的电路Verilog-HDL实现如下:

 module conv_ctlr(rst_n,clk,start,coe_rom_addr,rd_data_dpram_addr,acc_clr,wren,wr_data_dpram_addr,flag,mac_en);
//卷积控制信号产生电路模块
//可以控制一个MAC电路,分多个时钟周期,实现多个数值的相加。
//这里实现的是控制16级卷积的功能
input rst_n;//低电平复位信号,可以复位首地址指针
input clk;//工作时钟信号
input start;//启动一次控制逻辑输出的启动信号,下降启动一轮操作
output[:] coe_rom_addr;//参与卷积的固定信号rom地址信号
output[:] rd_data_dpram_addr;//读取双口RAM缓冲中数据的地址信号
output acc_clr; //累加器清零信号,高电平用于清除MAC电路的结果,准备下一次卷积计算
output wren; //写使能信号,每个start周期向下一个DPRAM的缓冲(本级的缓冲区也可以使用这个写入信号)里写入一个新数据的使能信号
output[:] wr_data_dpram_addr;//写入DPRAM缓冲区的新数据的地址线
output flag;//标志信号,表示卷积电路在工作
output mac_en;//乘加器的使能信号,为1时每个上升沿执行乘加
wire flag;//状态标志,为1时表示正在进行卷积操作,否则表示没有操作
reg[:] flag_cnt;//状态计数器,start信号到来后还是计数,当其大于一定值后切换标志
reg[:] current_pt;//当前位置指针,会在每次start到来卷积后加一,以指向下一次数据缓冲器的首地址
assign acc_clr = start;
assign mac_en = ((flag_cnt[:]>='d3)&(flag_cnt[9:0]<=10'd20))? 'b1 : 1'b0;//只有当flag_cnt等于3时系数和dpram才能读出所需的数据,注意读锁存器造成的一个周期的延迟。
///////向后续卷积节传递最老的一个数据的控制信号
assign wren = (flag_cnt[:] == 'd20)? 1'b1 : 'b0;//这里要看仿真时序图才能明白,flag_cnt=20的周期刚好读出本轮以后不再使用的数据
assign wr_data_dpram_addr[:] = current_pt[:];
always @ (posedge start or negedge rst_n)
begin
if(!rst_n)
current_pt[:] <= 'b1111;//复位后为最大值,第一个start脉冲使其从0开始
else
current_pt[:] <= current_pt[:] + 'd1;//首地址缓冲器,会在每次采样(或start)信号到来后加一,为下次输入新数据移动缓冲器做好准备
end
assign flag = ((flag_cnt[:]>='d2)&(flag_cnt[9:0]<=10'd20))? 'b1 : 1'b0;
always @ (negedge clk or posedge start)//注意为了让flag从clk下降沿开始,以上升沿为每个周期的中心,这里用用flag的下降沿计数
begin
if(start)
begin
flag_cnt[:] <= 'd0;
end
else begin
if(flag_cnt[:] <= ('d16 + 10'd1 + 'd3))
//计到15再加1,则一共1-16个脉冲;加1是为了留出第一个时钟周期作为dpram的地址潜伏期;加2是为了等待乘法器的潜伏期(潜伏期为3,但最后一个不用乘加)
begin
flag_cnt[:] <= flag_cnt[:] +'d1;
end
else
begin
flag_cnt[:] <= flag_cnt[:];
end
end
end
pset_addr_cnt i_rd_addr_cnt(//例化读缓冲当前地址计数器
.rst_n(rst_n),
.load(!flag),//每产生一个启动信号,就要重新对首地址置新值
.clk(clk),
.pre_value(current_pt),
.addr_cnt(rd_data_dpram_addr)
);
addr_cnt i_coe_rom_addr_cnt(//例化系数地址产生计数器
.en(flag),
.clk(clk),
.addr_cnt(coe_rom_addr)
);
endmodule module addr_cnt(en,clk,addr_cnt);
//本模块产生4位计数值,作为地址产生器
input en;//高电平有效
input clk;
output[:] addr_cnt;
reg[:] addr_cnt;
always @ (negedge clk or negedge en)//为了使地址再时钟下降沿产生,上升沿位于数据中央,clk使用了下降沿
begin
if(!en)
addr_cnt[:] <= 'd0;
else
addr_cnt[:] <= addr_cnt[:] + 'd1;
end
endmodule //带预置功能的地址计数器,4位
module pset_addr_cnt(rst_n,load,clk,pre_value,addr_cnt);
input rst_n;
input load;//load高电平时同步加载初值
input clk;
input[:] pre_value;//输入的预置初值
output[:] addr_cnt;//计数输出
reg[:] addr_cnt;
always @(negedge clk or negedge rst_n)//为了使地址再时钟下降沿产生,上升沿位于数据中央,clk使用了下降沿
begin
if(!rst_n)
addr_cnt[:] <= 'd0;//pre_value[3:0];
else begin
if(load == 'b1)
addr_cnt[:] <= pre_value[:];
else
addr_cnt[:] <= addr_cnt[:] + 'd1;
end
end
endmodule

上述代码中,需要特别注意的是数据缓冲区“当前地址寄存器”current_pt[3:0],它会在每个采样点的计算卷积运算开始之前,在启动信号start驱动下自动加一,随后current_pt[3:0]作为初值加载给数据缓冲区读地址寄存器/计数器“rd_data_dpram_addr”,从而起到了修正环形队列首地址的目的。这一操作保证了数据缓冲区的首地址指针总是指向环形队列数据结构中最新的数据。

另外,写使能信号wren是每个卷积节向后级的卷积节输出的控制信号——它在数据缓冲区读出最老数据的同时,使能后级卷积节数据缓冲区的写入功能,从而将前级卷积节中数据缓冲中最老数据作为最新信号存入后级卷积节数据缓冲区。

三、卷积节中的两个存储以及乘加电路的实现

正如我在本文第一部分“总体电路结构”中介绍的,每个卷积节中含有两个有M4K块实现的存储块:绿色部分是存储输入数据s[k]的缓冲区,和蓝色部分的卷积系数h[k]的存储器。分别采用Quartus-II中的MegaWizard实现,其结构如下图所示。

图2 双端口数据缓冲区的结构示意图

数据宽度为16位,是由ADC的位数12bits决定的。地址宽度为4位则是由16(即N/L的值)决定的。值得注意点是该双口RAM的输入和输出端各有一级D触发器构成的缓冲器,在规划控制时序时需要注意它们造成的数据潜伏期的增加。

图3 系数存储器的结构示意图

系数存储器只要设计为单口ROM即可满足需要,但为了使系数的初始化更加方便,我将它设计为双口RAM结构。这将允许系统在FPGA上电后,执行一个系数存储器初始化过程,以将系数从双口RAM的写入端口分时写入各个卷积节中。系数初始化的过程和电路设计将在本博文的后面详述。

每个卷积节中的乘加器,将在两次采样间隔间实现16(即N/L的值)次MAC操作,采用MageWizard实现的MAC结构如下所示。

图4 乘加器结构示意图

为防止溢出,乘加器模块输出宽度取了40bits,实际上每个卷积节只执行16次乘加,只需36bits就可以保证不溢出。

四、卷积节的顶层连接

为了将上述卷积节控制电路、数据缓冲器、系数存储器和乘加器连接为图1中的一个完整卷积节,还需要一个顶层设计文件如下。

 module CONV_SER16(clk,a,en,coe_data_in16,wr_coe_addr,wr_coe_clk,wr_coe_en,start,shft_out_dp_data,s_latch);
//本模块例化了一个乘加模块,采用串行方式实现16阶卷积/FIR运算,
//由start信号启动,持续时间约为20个clk周期。a为不断送入的被卷积数据流信号,s为卷积后输出的数据流,这两个流信号都被start同步
//在启动之前需要由系数配置模块向本节系数存储器配置系数,配置完成后通过en和start启动本模块滤波
input clk;//外部送入的100M左右时钟
input[:] a;//输入数据
input en;//高电平使能,由系数初始化模块控制,初始化完成后使能所有计算模块
input[:] coe_data_in16;//从本模块以外写入的配置系数
input[:] wr_coe_addr;//从本模块以外写入的配置系数地址
input wr_coe_clk;//从本模块以外输入的系数配置时钟
input wr_coe_en;//从本模块以外输入的系数配置使能端
input start;
output[:] s_latch;//经过锁存的卷积/FIR结果数据
output[:] shft_out_dp_data;//从DPRAM中读取的数,在本模块中参与MAC,同时输出给下一个卷积节作为输入
wire[:] s;
wire[:] coe_rom_addr;//参与卷积的固定信号rom地址信号
wire[:] rd_data_dpram_addr;//读取双口RAM缓冲中数据的地址信号
wire[:] wr_data_dpram_addr;//写入DPROM缓冲的地址信号
wire[:] coe_value;//读取系数值的连线
wire[:] dp_rd_data;//从DPRAM中读取的准备参与乘加的被卷积数
wire acc_clr; //累加器清零信号,高电平用于清除MAC电路的结果,准备下一次卷积计算
wire flag; //标志信号,表示卷积电路在工作
wire wren; //DPROM缓冲写使能,高电平使能
wire clk;//100M时钟
wire mac_en;//乘加器使能信号
assign shft_out_dp_data[:] = dp_rd_data[:];//从DPRAM中读取的数,在本模块中参与MAC,同时输出给下一个卷积节作为输入 conv_ctlr i_conv_ctlr(
.rst_n(en),//低电平复位信号,可以复位首地址指针
.clk(clk),//工作时钟信号
.start(start),//启动一次控制逻辑输出的启动信号,下降启动一轮操作
.coe_rom_addr(coe_rom_addr),//参与卷积的固定信号rom地址信号
.rd_data_dpram_addr(rd_data_dpram_addr),//读取双口RAM缓冲中数据的地址信号
.acc_clr(acc_clr), //累加器清零信号,高电平用于清除MAC电路的结果,准备下一次卷积计算
.wren(wren), //写使能信号,每个start周期向DPRAM的缓冲里写入一个新数据的使能信号
.wr_data_dpram_addr(wr_data_dpram_addr),//写入DPRAM缓冲区的新数据的地址线
.flag(flag),//标志信号,表示卷积电路在工作
.mac_en(mac_en)
);
MAC1616_40 i_mac(//例化乘加模块
.aclr3(acc_clr),
.clock0(!clk),//让乘加发生在flag为高电平阶段的clk的下降沿,因为读出数值发生在上升沿
.dataa(dp_rd_data),
.datab(coe_value),
.ena0(mac_en),//乘加使能信号
.result(s)
);
DUAL_PORT_BUFF i_dpram_buff(//例化存储缓冲区的PDRAOM
.data(a),//输入数据
.inclock(clk),
.outclock(clk),
.rdaddress(rd_data_dpram_addr),
.wraddress(wr_data_dpram_addr),
.wren(wren),
.q(dp_rd_data)
);
coe_dpram i_coe_dpram (//例化每一节的系数dpram,它负责在复位后接收系数池中初始化的数据
//这个例化对象的写入侧外接,用初始化器写入数据,读出端接在本模块中,负责向乘加器输出系数
.data ( coe_data_in16 ),//从本模块外部写入系数的写入端
.rdaddress ( coe_rom_addr ),//本模块自己产生的读系数地址
.rdclock ( clk & flag ),//本模块自己的读时钟
.wraddress ( wr_coe_addr ),//外部配置模块产生的写入地址
.wrclock ( wr_coe_clk ),//外部配置模块产生的写系数时钟
.wren ( wr_coe_en ),//外部配置模块产生的写使能,由配置模块的高地址译码产生
.q ( coe_value )//本模块读取的系数值
);
latch_40 i_latch_40(//例化40位锁存器,用以使计算结果在整个周期内保持不变
.din(s),
.dout(s_latch),
.clk(start)
);
endmodule

由于代码中由详细注释,这里就不再一一解释了。

五、系数初始化器的设计

完成卷积节的设计后,可以将其例化为L个卷积节,并通过逐一级联它们来实现更高阶的卷积/互相关/FIR滤波功能。但我发现一个很不方便的地方:例化产生的所有实例的系数存储器具有相通的内容,无法分别赋值。苦恼多时之后,终于一咬牙决定再写一个系数初始化模块来实现系数的初始化。这也就有了前面所说的,将每个卷积节中的系数存储器配置为可写入的双口RAM的事情。如果有朋友有更好的办法解决这个问题烦请告知,欢迎交流。

系数初始化模块由控制逻辑、系数池ROM和译码电路三部分组成。其中系数池ROM负责存储所有的卷积/互相关模板h[k]或M[k]系数,FPGA上电后,控制逻辑部分会先阻止卷积部分电路的工作,先进行系数配置。系数配置时,控制电路会从系数池ROM中依次读出每个卷积节所需的系数,并在译码电路的控制下将其写入每个卷积节中的系数存储器中(双口RAM,结构如图3所示)。系数初始化模块的Verilog-HDL代码如下所示。

 module init_coe_blk(clk,rst_n,ready,wr_blk_addr,data_bank,csh0,csh1,csh2,csh3);//,rd_blk_add2,blk_data2);
input clk;
input rst_n;//总的复位信号
output ready;//配置完成信号,高电平表示配置完成
output[:] wr_blk_addr;//系数blk的地址,比cnt_bank_addr延迟了一个时钟周期
output[:] data_bank;//从系数池读出的数据
output csh0,csh1,csh2,csh3;//用高电平选同各个系数blk
wire[:] cnt_bank_addr;//系数池地址
coe_init_addr i_coe_init_addr(//例化地址生成模块
.rst_n(rst_n),
.clk(clk),
.ready(ready),
.cnt_bank_addr(cnt_bank_addr),//给系数池的地址
.wr_blk_addr(wr_blk_addr)//给系数blk的地址,比cnt_bank_addr晚一个时钟。原因是系数池ROM有一个周期的读出延迟
);
encode i_encode(//例化地址译码模块
.encode_adder(wr_blk_addr),//被译码的地址是经过延迟的地址,因为这个译码是为写入进行译码
.csh0(csh0),
.csh1(csh1),
.csh2(csh2),
.csh3(csh3)
);
coe_bank_rom i_coe_bank_rom (//例化输出数据配置数据的rom bank
.address ( cnt_bank_addr ),//由计数器产生的地址
.clken ( rst_n ),
.clock ( clk ),//时钟
.q ( data_bank )//系数池读出的数据
);
endmodule module coe_init_addr(rst_n,clk,ready,cnt_bank_addr,wr_blk_addr);
input rst_n,clk;
output ready;//配置完成信号
output[:] cnt_bank_addr;//读系数池的地址信号
output[:] wr_blk_addr;//向被配置系数blk发送的地址信号,由于系数池有读出延迟,wr_blk_addr比cnt_bank_addr要多延迟一个周期,由级联的D触发器实现
reg ready;
reg[:] cnt_bank_addr10;//10位的计数器,其实只需要第8位,多余的位为更大的系数池预留的
reg[:] wr_blk_addr;
assign cnt_bank_addr[:] = cnt_bank_addr10[:];
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cnt_bank_addr10[:] <= 'd0;
ready <= 'b0;
end
else begin
if(cnt_bank_addr10[:] < 'hff)
begin
cnt_bank_addr10[:] <= cnt_bank_addr10[:] + 'd1;
ready <= 'b0;
end
else begin
cnt_bank_addr10[:] <= cnt_bank_addr10[:];
ready <= 'b1;
end
end
end
//加一级D触发器,对地址延迟一个时钟周期,以对消系数池读取的延迟
always @ (posedge clk or negedge rst_n)
if(!rst_n)
begin
wr_blk_addr[:] <= 'd0;
end
else begin
wr_blk_addr[:] <= cnt_bank_addr[:];
end
endmodule
module encode(encode_adder,csh0,csh1,csh2,csh3);//地址译码模块,用于产生每个coe模块所需的片选信号,注意可以增加译码结果片选信号
input[:] encode_adder;//被译码地址,有8位,高4位参与译码
output csh0,csh1,csh2,csh3;//片选信号,注意,是高电平有效。
assign csh0=(encode_adder[:] == 'd0)? 1'b1:'b0;
assign csh1=(encode_adder[:] == 'd1)? 1'b1:'b0;
assign csh2=(encode_adder[:] == 'd2)? 1'b1:'b0;
assign csh3=(encode_adder[:] == 'd3)? 1'b1:'b0;
endmodule

系数池ROM就是一个简单的单端口ROM,其结构如下图所示。

图5 系数池ROM的结构示意图

其大小为256个字,但由于N为64,我只是用了系数池ROM的1/4。

六、各卷积节求和电路的设计

如图1所示,还需要对L个卷积节的结果求和,才能得到半并行式互相关/卷积/FIR滤波器的最终结果。使用Quartus-II的MegaWizard调用PARALLEL_ADD这个IP,能实现最终求和。其结构如下图所示。

图6 并行加法器结构示意图

关于回波检测中功率(平方)计算、历史数据积分等算法在FPGA中的实际实现,请关注后续博文【目标反射回波检测算法及其FPGA实现之三:平方、积分电路及算法的顶层实现】。

关于目标回波检测算法原理和设计论证过程,请参看本人的上一篇博文【 目标反射回波检测算法及其FPGA实现 之一:算法概述 】。

目标反射回波检测算法及其FPGA实现 之二:互相关/卷积/FIR电路的实现的更多相关文章

  1. 目标反射回波检测算法及其FPGA实现 之一:算法概述

    目标反射回波检测算法及其FPGA实现之一:算法概述 前段时间,接触了一个声呐目标反射回波检测的项目.声呐接收机要实现的核心功能是在含有大量噪声的反射回波中,识别出发射机发出的激励信号的回波.我会分几篇 ...

  2. 目标反射回波检测算法及其FPGA实现 之三:平方、积分电路及算法的顶层实现

    目标反射回波检测算法及其FPGA实现之三: 平方.积分电路及算法的顶层实现 前段时间,接触了一个声呐目标反射回波检测的项目.声呐接收机要实现的核心功能是在含有大量噪声的反射回波中,识别出发射机发出的激 ...

  3. 目标反射回波检测算法及其FPGA实现(准备篇): 用Verilog-HDL状态机控制硬件接口

    基于FPGA的目标反射回波检测算法及其实现(准备篇) :用Verilog-HDL状态机控制硬件接口 前段时间,开发了一个简单的目标反射回波信号识别算法,我会分几篇文章分享这个基于FPGA的回波识别算法 ...

  4. Harris角点检测算法优化

    Harris角点检测算法优化 一.综述 用 Harris 算法进行检测,有三点不足:(1 )该算法不具有尺度不变性:(2 )该算法提取的角点是像素级的:(3 )该算法检测时间不是很令人满意. 基于以上 ...

  5. 基于dsp_builder的算法在FPGA上的实现(转自https://www.cnblogs.com/sunev/archive/2012/11/17/2774836.html)

    一.摘要 结合dsp_builder.matlab.modelsim和quartus ii等软件完成算法的FPGA实现. 二.实验平台 硬件平台:DIY_DE2 软件平台:quartus ii9.0 ...

  6. 基于dsp_builder的算法在FPGA上的实现

    基于dsp_builder的算法在FPGA上的实现   一.摘要 结合dsp_builder.matlab.modelsim和quartus ii等软件完成算法的FPGA实现. 二.实验平台 硬件平台 ...

  7. 浅谈Virtual Machine Manager(SCVMM 2012) cluster 过载状态检测算法

    在我们使用scvmm2012的时候,经常会看到群集状态变成了这样 点开看属性后,我们发现是这样 . 发现了吗?Over-committed,如果翻译过来就是资源过载,或者说资源过量使用了,那么这个状态 ...

  8. 异常检测算法--Isolation Forest

    南大周志华老师在2010年提出一个异常检测算法Isolation Forest,在工业界很实用,算法效果好,时间效率高,能有效处理高维数据和海量数据,这里对这个算法进行简要总结. iTree 提到森林 ...

  9. 机器学习:异常检测算法Seasonal Hybrid ESD及R语言实现

    Twritters的异常检测算法(Anomaly Detection)做的比较好,Seasonal Hybrid ESD算法是先用STL把序列分解,考察残差项.假定这一项符合正态分布,然后就可以用Ge ...

随机推荐

  1. PRINCE2是什么?

    PRINCE是PRoject IN Controlled Environment(受控环境下的项目管理)的简称. PRINCE2描述了如何以一种逻辑性的.有组织的方法,按照明确的步骤对项目进行管理. ...

  2. leetCode题解之Self Dividing Numbers

    1.题目描述 2.题目分析 简单题目,只要挨个判断该数是不是满足条件即可. 3.代码 vector<int> selfDividingNumbers(int left, int right ...

  3. PHP获取用户的真实IP地址

    本文出至:新太潮流网络博客 PHP获取用户的真实IP地址,非代理IP function getClientIP(){ global $ip; if(getenv("HTTP_CLIENT_I ...

  4. 关于SQL Server 2017中使用json传参时解析遇到的多层解析问题

    开发新的系统,DB部分使用了SQL Server从2016版开始自带的Json解析方式. 用了快半年,在个人项目,以及公司部分项目上使用了,暂时还没遇到大的问题,和性能问题. 今天在解析Json的多级 ...

  5. ASP.NET 通过配置hiddenSegment禁止目录下资源通过Url形式访问

    根据默认的ASP.NET配置,App_Data下的资源是禁止通过Url形式直接访问的,在实际开发中,可能也会有这样的需求,比如某些是系统资源目录,该目录下的资源也需要像App_Data目录一样禁止访问 ...

  6. orcl数据库查询重复数据及删除重复数据方法

    工作中,发现数据库表中有许多重复的数据,而这个时候老板需要统计表中有多少条数据时(不包含重复数据),只想说一句MMP,库中好几十万数据,肿么办,无奈只能自己在网上找语句,最终成功解救,下面是我一个实验 ...

  7. 使用yii AR 完成单个表的CURD操作

    什么是AR(ActiveRecord) Active Record (活动记录,以下简称AR)提供了一个面向对象的接口, 用以访问数据库中的数据.一个 AR 类关联一张数据表, 每个 AR 对象对应表 ...

  8. September 19th 2017 Week 38th Tuesday

    Live boldly. Push yourself. Don't settle. 勇敢生活,突破自我,永不设限! Don't indulge in the past, whether it was ...

  9. 硬盘上的一些算法小题目||and今天看了下林锐的书以及gdb调试 及一些变成算法小题目

    gdb调试:观察点,断点,事件捕捉点.step 进入函数,next 跳过函数,until 跳出循环,finish 结束函数 林锐:书后试题 & c++的对象模型图 看了二叉树的非递归遍历, 链 ...

  10. 用eval似乎会执行结果一次性返回,结果显示的是一行

    with open(r'商品资料','r',encoding='utf-8') as f1: lis_goods = eval(f1.read()) # 用eval似乎会执行结果一次性返回,结果显示的 ...