本文的思路框架:
①本文采用支持3x3算子模块和5x5算子模块的生成,用于后一级别的算法输入
②本例程中采用的FPGA设计技巧,可用于借鉴,一是generate if参数定义;二是调用xilinx和altera的sync fifo和async fifo原语实现不同平台同步fifo和异步fifo的功能,省去ip核的调用,简化代码移植
一、算子模板基础知识
在图像处理过程中,需要对图像进行滤波操作,在进行滤波操作通常使用算子模板,即扫描窗模板,一般有 3x3、5x5 等模板形式
3x3算子模板
5x5算子模板
二、FPGA设计思路
使用 FIFO 来缓存图像的行数据,如果取 3x3 的模板,那么至少需要两个深度大于图像行数据的长度的 FIFO,通过首尾相连的形式来缓存两行数据,等第三行数据到来之时,同时输出三行数据。
同理如果是5x5的模板,需要四个深度大于行数据长度的FIFO,通过收尾相连的形式来缓存四行数据,等第五行数据到来之时,同时输出五行数据。其余类推即可。
3x3模板设计及部分代码分析
代码实现功能分析:
三、FPGA设计技巧
1、generate if参数定义,未选择部分,eda软件会自动优化掉,不会造成逻辑资源浪费。
2、调用xilinx和altera的sync fifo和async fifo原语实现不同平台同步fifo和异步fifo的功能,省去ip核的调用,简化代码移植
①xilinx sync fifo和async fifo的原语调用
generateif(ASYNC_CLK == 1)begin : ASYNC_FIFO xpm_fifo_async #(.CDC_SYNC_STAGES(3), // DECIMAL.DOUT_RESET_VALUE("0"), // String.ECC_MODE("no_ecc"), // String.FIFO_MEMORY_TYPE(FIFO_MEMORY_TYPE), // String.FIFO_READ_LATENCY(FIFO_READ_LATENCY), // DECIMAL.FIFO_WRITE_DEPTH(FIFO_DEPTH), // DECIMAL.FULL_RESET_VALUE(1), // DECIMAL.PROG_EMPTY_THRESH(5), // DECIMAL.PROG_FULL_THRESH(PROG_FULL_THRESH), // DECIMAL.RD_DATA_COUNT_WIDTH(COUNT_WIDTH), // DECIMAL.READ_DATA_WIDTH(WRITE_DATA_WIDTH), // DECIMAL.READ_MODE(FIFO_READ_MODE), // String.RELATED_CLOCKS(0), // DECIMAL.SIM_ASSERT_CHK(0), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages.USE_ADV_FEATURES("1707"), // String.WAKEUP_TIME(0), // DECIMAL.WRITE_DATA_WIDTH(WRITE_DATA_WIDTH), // DECIMAL.WR_DATA_COUNT_WIDTH(COUNT_WIDTH) // DECIMAL)xpm_fifo_inst (.almost_empty (), //unused .almost_full (), //unused.data_valid (),.dbiterr (), .dout (o_rd_data ), .empty (o_rd_empty ), .full (o_wr_full ), .overflow (), .prog_empty (o_rd_arempty ), .prog_full (o_wr_awfull ), .rd_data_count (o_rd_cnt ),.rd_rst_busy (), .sbiterr (), .underflow (), .wr_ack (), //unused .wr_data_count (o_wr_cnt ),.wr_rst_busy (), .din (i_wr_data ), .injectdbiterr (1'b0),.injectsbiterr (1'b0),.rd_clk (i_rd_clk ), .rd_en (i_rd_en ), .rst (i_wr_rst || i_rd_rst ), .sleep (1'b0), .wr_clk (i_wr_clk ), .wr_en (i_wr_en ) );end// End of xpm_fifo_async_inst instantiationelse begin : SYNC_FIFOxpm_fifo_sync #(.DOUT_RESET_VALUE("0"), // String.ECC_MODE("no_ecc"), // String.FIFO_MEMORY_TYPE(FIFO_MEMORY_TYPE), // String.FIFO_READ_LATENCY(FIFO_READ_LATENCY), // DECIMAL.FIFO_WRITE_DEPTH(FIFO_DEPTH), // DECIMAL.FULL_RESET_VALUE(1), // DECIMAL.PROG_EMPTY_THRESH(5), // DECIMAL.PROG_FULL_THRESH(PROG_FULL_THRESH), // DECIMAL.RD_DATA_COUNT_WIDTH(COUNT_WIDTH), // DECIMAL.READ_DATA_WIDTH(WRITE_DATA_WIDTH), // DECIMAL.READ_MODE(FIFO_READ_MODE), // String.SIM_ASSERT_CHK(0), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages.USE_ADV_FEATURES("1707"), // String.WAKEUP_TIME(0), // DECIMAL.WRITE_DATA_WIDTH(WRITE_DATA_WIDTH), // DECIMAL.WR_DATA_COUNT_WIDTH(COUNT_WIDTH) // DECIMAL)xpm_fifo_inst (.almost_empty (), //unused .almost_full (), //unused.data_valid (), .dbiterr (), .dout (o_rd_data ), .empty (o_rd_empty ), .full (o_wr_full ), .overflow (), .prog_empty (o_rd_arempty ), .prog_full (o_wr_awfull ), .rd_data_count (o_rd_cnt ),.rd_rst_busy (), .sbiterr (), .underflow (), .wr_ack (), //unused .wr_data_count (o_wr_cnt ),.wr_rst_busy (), .din (i_wr_data ), .injectdbiterr (1'b0),.injectsbiterr (1'b0),.rd_en (i_rd_en ), .rst (i_wr_rst ), .sleep (1'b0), .wr_clk (i_wr_clk ), .wr_en (i_wr_en ) );end
endgenerate
②altera sync fifo和async fifo的原语调用
generate if(ASYNC_CLK == 1)begin : ASYNC_FIFO dcfifo dcfifo_component (.rdclk (i_rd_clk ),.wrclk (i_wr_clk ),.wrreq (i_wr_en ),.data (i_wr_data ),.rdreq (i_rd_en ),.wrempty (o_rd_empty ),.wrfull (o_wr_full ),.q (o_rd_data ),.rdempty (o_rd_arempty ),.rdfull (o_wr_awfull ),.wrusedw (o_wr_cnt ),.rdusedw (o_rd_cnt ),.aclr ( ));defparamdcfifo_component.intended_device_family = DEVICE,dcfifo_component.lpm_numwords = FIFO_DEPTH,dcfifo_component.lpm_showahead = FIFO_READ_MODE,dcfifo_component.lpm_type = "dcfifo",dcfifo_component.lpm_width = DATA_WIDTH,dcfifo_component.lpm_widthu = ADDR_WIDTH,dcfifo_component.overflow_checking = "ON",dcfifo_component.rdsync_delaypipe = 3,dcfifo_component.underflow_checking = "ON",dcfifo_component.use_eab = "ON",dcfifo_component.wrsync_delaypipe = 3; end// End of xpm_fifo_async_inst instantiationelse begin : SYNC_FIFO scfifo scfifo_component(.clock (i_wr_clk ),.sclr (i_wr_rst ),.wrreq (i_wr_en ),.data (i_wr_data ),.rdreq (i_rd_en ),.usedw (o_wr_cnt ),.empty (o_rd_empty ),.full (o_wr_full ),.q (o_rd_data ),.almost_empty (o_rd_arempty ),.almost_full (o_wr_awfull ),.aclr ( ));defparamscfifo_component.add_ram_output_register = "OFF",scfifo_component.almost_empty_value = 2,scfifo_component.almost_full_value = PROG_FULL_THRESH,scfifo_component.intended_device_family = DEVICE,scfifo_component.lpm_numwords = FIFO_DEPTH,scfifo_component.lpm_showahead = FIFO_READ_MODE,scfifo_component.lpm_type = "scfifo",scfifo_component.lpm_width = DATA_WIDTH,scfifo_component.lpm_widthu = ADDR_WIDTH,scfifo_component.overflow_checking = "ON",scfifo_component.underflow_checking = "ON",scfifo_component.use_eab = "ON"; end
endgenerate
③xilinx和altera平台fifo选择
generateif(DEVICE_CHOODE == "xilinx")begin : XILINX xilinx_fifo #(.DATA_WIDTH (DATA_WIDTH ),.ASYNC_CLK (ASYNC_CLK ),.ADDR_WIDTH (ADDR_WIDTH ),.READ_MODE (READ_MODE )//0:STA fifo 1:FWFT)xilinx_fifo_init(.i_wr_clk (i_wr_clk ),.i_wr_rst (i_wr_rst ),.i_wr_en (i_wr_en ),.i_wr_data (i_wr_data ),.o_wr_cnt (o_wr_cnt ),.o_wr_full (o_wr_full ),.o_wr_awfull (o_wr_awfull ), .i_rd_clk (i_rd_clk ),.i_rd_rst (i_rd_rst ),.i_rd_en (i_rd_en ),.o_rd_data (o_rd_data ),.o_rd_cnt (o_rd_cnt ),.o_rd_empty (o_rd_empty ),.o_rd_arempty (o_rd_arempty ) ); endelse begin : ALTERAaltera_fifo #(.DATA_WIDTH (DATA_WIDTH ),.ASYNC_CLK (ASYNC_CLK ),.ADDR_WIDTH (ADDR_WIDTH ),.READ_MODE (READ_MODE )//0:STA fifo 1:FWFT)altera_fifo_init(.i_wr_clk (i_wr_clk ),.i_wr_rst (i_wr_rst ),.i_wr_en (i_wr_en ),.i_wr_data (i_wr_data ),.o_wr_cnt (o_wr_cnt ),.o_wr_full (o_wr_full ),.o_wr_awfull (o_wr_awfull ), .i_rd_clk (i_rd_clk ),.i_rd_rst (i_rd_rst ),.i_rd_en (i_rd_en ),.o_rd_data (o_rd_data ),.o_rd_cnt (o_rd_cnt ),.o_rd_empty (o_rd_empty ),.o_rd_arempty (o_rd_arempty ) ); end
endgenerate
④xilinx vivado平台开发及仿真验证
⑤altera quartus平台开发及仿真验证