一、简述
在对图像进行处理时经常用到矩阵操作,包括sobel边缘检测、中值滤波、形态学等。本篇博客介绍一下用两个RAM生成 3x3 矩阵的方法。
二、实现方法
1.设计line_shift模块用于对三行数据进行寄存;
2.设计一个产生3x3矩阵的模块。
三、实现过程
1.line_shift_RAM_24bit
通过时钟使能信号对RAM的地址进行计数,计得的数就是对应的列(col),即横坐标。由于 RAM 地址在 per_frame_href 信号为低电平时清零;而当新的一行到达时,per_frame_href 信号为高电平,RAM 地址开始累加,所以 RAM 的地址等于每行图像像素的横坐标。以该地址读出对应列的数据,用于上层模块生成“三行一列”的像素数据
//在数据到来时,RAM的读地址累加 always @(posedge clock)begin if(pre_frame_href) if(clken) ram_rd_addr <= ram_rd_addr + 1; else ram_rd_addr <= ram_rd_addr;//当前矩阵位置 else ram_rd_addr <= 0; end
对时钟、地址、数据延迟以同步数据输出,延迟3拍是因为从RAM中读取数据以及向RAM0、RAM1中更新数据各需要花费一个时钟周期
`//对时钟使能信号延迟3拍
always @(posedge clock)begin
clken_dly <= {clken_dly[1:0],clken};
end
//将RAM地址延迟2拍
always @(posedge clock)begin
ram_rd_addr_d0 <= ram_rd_addr;
ram_rd_addr_d1 <= ram_rd_addr_d0;
end
//输入数据延迟3拍送入RAM
always @(posedge clock)begin
shiftin_d0 <= shiftin;
shiftin_d1 <= shiftin_d0;
shiftin_d2 <= shiftin_d1;
end![](/i/l/?n=24&i=blog/3457001/202406/3457001-20240603154852488-1048414967.png)
//用于存储前一行图像的RAM
blk_mem_gen_0 u_ram_1024x8_0(
.clka (clock),
.wea (clken_dly[2]),
.addra (ram_rd_addr_d1),//在延迟的第三个时钟周期,当前行的数据写入RAM0
.dina (shiftin_d2),
.clkb (clock),
.addrb (ram_rd_addr),
.doutb (taps0x)//延迟一个时钟周期,输出RAM0中前一行图像的数据
);
//寄存前一行的图像数据
always @(posedge clock)begin
taps0x_d0 <= taps0x;
end
//用于存储前前一行图像的RAM
blk_mem_gen_0 u_ram_1024x8_1(
.clka (clock),
.wea (clken_dly[1]),
.addra (ram_rd_addr_d0),
.dina (taps0x_d0),//在延迟 第二个时钟周期,将前一行图像的数据写入RAM1
.clkb (clock),
.addrb (ram_rd_addr),
.doutb (taps1x)//延迟一个时钟周期,输出RAM1中前前一行的图像的数据
);这里例化了两个伪双端口的RAM(一个只能读,一个只能写),用于存储两行数据。 RAM配置,选择“Primitives Output Register”时RAM 中的数据会寄存一个周期后输出 ![](/i/l/?n=24&i=blog/3457001/202406/3457001-20240603180851748-1321758282.png) ![](/i/l/?n=24&i=blog/3457001/202406/3457001-20240603180915102-379260596.png) 2.生成3x3矩阵 首先调用前面设计的line_shift模块输出三行对应的数据
//用于存储列数据的RAM
line_shift_RAM_24bit u_Line_Shift_RAM_24bit(
.clock (clk),
.clken (pre_frame_clken),
.pre_frame_href (pre_frame_href),
.shiftin (pre_img_Y),//当前行的数据
.taps0x (row2_data),//前一行输据
.taps1x (row1_data),//前前一行的数据
);
输出3x3矩阵模块,但在每行开头是通过用前面的数据补充来得到3x3模块,所以理论上在图像最上面和最左边会有前面数据的残余
在同步处理后的控制信号下,输出图像矩阵
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
{matrix_p11,matrix_p12,matrix_p13} <= 0;
{matrix_p21,matrix_p22,matrix_p23} <= 0;
{matrix_p31,matrix_p32,matrix_p33} <= 0;
end
else if(read_frame_href)begin
if(read_frame_clken)begin
{matrix_p11,matrix_p12,matrix_p13} <= {matrix_p12,matrix_p13,row1_data};
{matrix_p21,matrix_p22,matrix_p23} <= {matrix_p22,matrix_p23,row2_data};
{matrix_p31,matrix_p32,matrix_p33} <= {matrix_p32,matrix_p33,row3_data};
end
else begin
{matrix_p11,matrix_p12,matrix_p13} <= {matrix_p11,matrix_p12,matrix_p13};
{matrix_p21,matrix_p22,matrix_p23} <= {matrix_p21,matrix_p22,matrix_p23};
{matrix_p31,matrix_p32,matrix_p33} <= {matrix_p31,matrix_p32,matrix_p33};
end
end
else begin
{matrix_p11,matrix_p12,matrix_p13} <= 0;
{matrix_p21,matrix_p22,matrix_p23} <= 0;
{matrix_p31,matrix_p32,matrix_p33} <= 0;
end
end`
参考文献:
1.正点原子sdk中值滤波
(本文用作学习记录,如有侵权请联系作者)