为了尽量利用FPGA的并行性,可以考虑同时进行X方向和Y方向的计算。同时,由于,模板的数值为1和2或者-1,-2,我们考虑将负数和正数相加后再整体做减法。模板元素为2时直接进行移位操作则简单地多。
同时得到窗口内9个像素的值比较简单。两个行缓存加上当前行即可同时得到3行图像数据,将3行数据分别打两排即可得到一个窗口9个限售股数据。将9个数据命名如下表:
Sobel(0) | Sobel_r(0) | Sobel_r2(0) |
---|---|---|
Sobel(1) | Sobel_r(1) | Sobel_r2(1) |
Sobel(2) | Sobel_r(2) | Sobel_r2(2) |
缓存电路如下:
得到9个像素之后还需将分别对x和y方向的模板进行运算。由于两个模板中3个像素恒为0.世纪上需要完成6个数据加法运算,经过3个时钟的运算即可得出结果。
X方向的Sobel结果计算
X方向的Sobel结果计算
module sobel_module(
clk,
rst,
);
input clk;
input rst;
parameter DW = 14;
//9个窗口寄存器
reg [DW-1:0] sobel[0:3-1];
reg [DW-1:0] sobel_r[0:3-1];
reg [DW-1:0] sobel_r2[0:3-1];
//中间寄存器
reg [DW+4-1:0] sobel_result_temp[0:3];
reg [DW+3-1:0] sobel_temp[0:12];
//x和y方向计算结果寄存器
reg [21-1:0] sobel_result_x;
reg [21-1:0] sobel_result_y;
reg [2:0] j,k;
//x方向sobel模板计算
always @(posedge clk)
begin
if(rst)
begin
for( j = 0; j <= 6;j=j+1 )
sobel_temp[j] <= {DW+3{1'b0}};
sobel_result_temp[0] <= {DW+4{1'b0}};
end
else
begin
if(din_valid_r[1])
begin
sobel_temp[0] <= {{2'b00},sobel[1],1'b0}; //乘以2
sobel_temp[1] <= ({3'b000,sobel[0]}) + ({3'b000,sobel[2]});
sobel_temp[2] <= {{2'b00},sobel_r2[1],1'b0};
sobel_temp[3] <= ({3'b000,sobel_r2[0]}) + ({3'b000,sobel_r2[2]});
end
if(din_valid_r[2])
begin
sobel_temp[4] <= sobel_temp[0] + sobel_temp[1];
sobel_temp[5] <= sobel_temp[2] + sobel_temp[3];
end
if(din_valid_r[3])
begin
sobel_result_temp[0] <= ({1'b0,sobel_temp[4]}) - ({1'b0,sobel_temp[5]});
end
end
end
//y方向sobel模板计算
always @(posedge clk)
begin
if(rst)
begin
for( k = 0; k <= 6;k=k+1 )
sobel_temp[k] <= {DW+3{1'b0}};
sobel_result_temp[1] <= {DW+4{1'b0}};
end
else
begin
if(din_valid_r[1])
begin
sobel_temp[7] <= {{2'b00},sobel_r[0],1'b0}; //乘以2
sobel_temp[8] <= ({3'b000,sobel[0]}) + ({3'b000,sobel_r2[0]});
sobel_temp[9] <= {{2'b00},sobel_r[2],1'b0};
sobel_temp[10] <= ({3'b000,sobel[2]}) + ({3'b000,sobel_r2[2]});
end
if(din_valid_r[2])
begin
sobel_temp[11] <= sobel_temp[7] + sobel_temp[8];
sobel_temp[12] <= sobel_temp[9] + sobel_temp[10];
end
if(din_valid_r[3])
begin
sobel_result_temp[1] <= ({1'b0,sobel_temp[11]}) - ({1'b0,sobel_temp[12]});
end
end
end
//bufffer result for 1 clk and extend sign bits
always @(posedge clk)
begin
if(rst)
begin
sobel_result_temp[2] <= {DW+4{1'b0}};
sobel_result_temp[3] <= {DW+4{1'b0}};
sobel_result_x <= 21'b0;
sobel_result_y <= 21'b0;
end
else
begin
if(din_valid_r[4])
begin
sobel_result_temp[2] <= sobel_result_temp[0]; //x sobel result
sobel_result_temp[3] <= sobel_result_temp[1]; //y sobel result
end
if(din_valid_r[5])
begin
if(sobel_result_temp[2][DW+3]) //x<0
sobel_result_x <= {{21-DW-4{1'b1}},sobel_result_temp[2]};
else
sobel_result_x <= {{21-DW-4{1'b0}},sobel_result_temp[2]};
if(sobel_result_temp[3][DW+3]) //y<0
sobel_result_y <= {{21-DW-4{1'b1}},sobel_result_temp[3]};
else
sobel_result_y <= {{21-DW-4{1'b0}},sobel_result_temp[3]};
end
end
end
//得到9个缓存窗口
always @(*) sobel[0] <= din;
always @(*) sobel[1] <= line_dout[0];
always @(*) sobel[2] <= line_dout[1];
generate
begin :sobel_buf
genvar i;
for( i =0; i<=KSZ-1;i=i+1)
begin : sobel_buf_inst
always @(posedge clk)
begin
if(rst)
begin
sobel_r[i] <= {DW{1'b0}};
sobel_r2[i] <= {DW{1'b0}};
end
else
begin
sobel_r[i] <= sobel[i];
sobel_r2[i] <= sobel_r;
end
end
end
end
endgenerate
endmodule