当前位置:首页 > EDA > 电子设计自动化
[导读]720P即1280×720,按60fps算像素率约55.3M像素/秒,1像素/时钟用60~75MHz即可跑满;做预处理不存整帧,采用“灰度化—行缓冲—3×3 Sobel—阈值输出”流式管线最省资源。 先转灰度再进算法,避免RGB三通道各建行缓冲,BRAM和带宽都能降三分之一。


720P即1280×720,按60fps算像素率约55.3M像素/秒,1像素/时钟用60~75MHz即可跑满;做预处理不存整帧,采用“灰度化—行缓冲—3×3 Sobel—阈值输出”流式管线最省资源。 先转灰度再进算法,避免RGB三通道各建行缓冲,BRAM和带宽都能降三分之一。

一、行缓冲建3×3窗口

3×3卷积需同时取当前行、上1行、上2行。用两块BRAM存历史行、当前行直接移位,宽度1280、像素8bit;小分辨率可用XPM_SHIFT_RAM,大分辨率用Block RAM更省LUT。

module line3 #(parameter W=1280, BW=8)(

 input clk, rst_n, input vld, input [BW-1:0] din,

 output reg [BW-1:0] p0,p1,p2,p3,p4,p5,p6,p7,p8, output reg win_vld);

 reg [BW-1:0] ram0[0:W-1], ram1[0:W-1];

 reg [11:0] wa, ra;

 reg [BW-1:0] r0,r1,cur;

 reg [1:0] fill;

 always @(posedge clk or negedge rst_n) begin

   if(!rst_n) begin wa<=0;ra<=0;fill<=0;win_vld<=0; end

   else if(vld) begin

     ram0[wa]<=r0; ram1[wa]<=r1;            // 存上两行

     r0<=ram0[ra]; r1<=ram1[ra]; cur<=din;  // 读历史、锁当前

     // 3x3:p0..p8按行排列,边界外做镜像复制

     p0<=ra==0?r0:ram0[ra-1]; p1<=r0; p2<=ra==W-1?r0:ram0[ra+1];

     p3<=ra==0?r1:ram1[ra-1]; p4<=r1; p5<=ra==W-1?r1:ram1[ra+1];

     p6<=ra==0?cur:din;       p7<=cur; p8<=ra==W-1?cur:din;

     wa<=wa+1; ra<=ra+1;

     if(fill<2) fill<=fill+1;

     win_vld<=(fill==2);

   end

 end

endmodule

镜像填充比补零更稳,边缘不会被压暗;若输出允许裁2行2列,可省镜像逻辑、降低比较次数。

二、Sobel梯度与流水

Gx用[-1,0,1;-2,0,2;-1,0,1],Gy用[-1,-2,-1;0,0,0;1,2,1]。乘2用移位,不加乘法器;幅值用|Gx|+|Gy|近似,避免开方,硬件代价低、工业检测足够。

module sobel_core(input clk,rst_n,input vld,

 input [7:0] p0,p1,p2,p3,p4,p5,p6,p7,p8,

 input [7:0] th, output reg out_vld, output reg [7:0] edge);

 reg signed [10:0] gx,gy; reg [11:0] mag;

 always @(posedge clk or negedge rst_n) begin

   if(!rst_n) begin out_vld<=0; edge<=0; end

   else begin

     gx<=(p2+p8+{p5[7:0],1'b0})-(p0+p6+{p3[7:0],1'b0});

     gy<=(p6+p8+{p7[7:0],1'b0})-(p0+p2+{p1[7:0],1'b0});

     mag<= (gx[10]?-gx:gx)+(gy[10]?-gy:gy);

     out_vld<=vld;

     edge<= (mag[11:8]>th)?8'hFF:8'h00;   // 超阈值输出白边,否则黑

   end

 end

endmodule

三级打拍:取窗→算Gx/Gy→取绝对值求和并阈值,1像素/周期稳定出数。720P行消隐期间可插入帧复位,避免跨行窗口错位。

三、AXI-Stream与背压

摄像头、VDMA、HDMI都走AXI4-Stream,模块按tvalid/tready握手;下游慢就在前端放同步FIFO,行缓冲不因tready拉低而丢窗。

module sobel_axis(input clk,rst_n,

 input [7:0] s_tdata, input s_tvalid, output s_tready,

 output reg [7:0] m_tdata, output reg m_tvalid, input m_tready);

 reg [7:0] p0,p1,p2,p3,p4,p5,p6,p7,p8; reg win;

 line3 #(1280,8) L(clk,rst_n,s_tvalid,s_tdata,p0,p1,p2,p3,p4,p5,p6,p7,p8,win);

 sobel_core C(clk,rst_n,win,p0,p1,p2,p3,p4,p5,p6,p7,p8,8'd40,m_tvalid,m_tdata);

 assign s_tready = m_tready;   // 简单透传;高吞吐改FIFO解耦

endmodule

阈值th走AXI-Lite由CPU/寄存器配置,按光照自适应;弱光调低、强光调高,减少误边。

四、资源与调试

先灰度后缓存:RGB888转Y=77R+150G+29B再>>8,只缓存8bit单通道,720P两行历史约1280×2=2560字节,小块BRAM即可。

行缓冲用Block RAM,别用分布式RAM;纯移位可用XPM_SHIFT_RAM,深度1280不占很多逻辑。

关键路径在Gx/Gy加法,拆三级寄存;目标Artix-7 100~150MHz、Kintex/Zynq可上更高。

跨时钟:传感器PCLK与处理时钟不同时,入口异步FIFO,避免亚稳态;输出到HDMI再按像素时钟出。

验证:ModelSim喂单竖线/单横线/灰度图,看p0~p8窗口、gx/gy符号、edge二值;ILA抓s_tvalid/s_tready/m_tdata,对比Matlab/OpenCV参考图,PSNR一般可



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭