1 顶层代码
`timescale 1ns / 1ps
//边缘检测二阶微分算子:canny算子
module image_canny_edge_detect (
input clk,
input reset, //复位高电平有效
input [10:0] img_width,
input [ 9:0] img_height,
input [ 7:0] low_threshold,
input [ 7:0] high_threshold,
input valid_i,
input [15:0] rgb_565_i, // 输入的16位RGB图像数据
output valid_o,
output [15:0] rgb_565_o // 输出的16位RGB图像数据
);
//变量声明
wire valid_gray;
wire [7:0] img_data_gray;
wire valid_gf;
wire [7:0] img_data_gf;
wire valid_sbl;
wire [7:0] grad_mag;
wire [10:0] grad_dx;
wire [10:0] grad_dy;
wire valid_nms;
wire [7:0] img_data_nms;
wire valid_db;
wire [7:0] img_data_db;
wire [23:0] img_data_i, img_data_o;
assign img_data_i = {rgb_565_i[15:11], 3'b000, rgb_565_i[10:5], 2'b00, rgb_565_i[4:0], 3'b000};
assign rgb_565_o = {{img_data_o[23:19], img_data_o[15:10], img_data_o[7:3]}};
//彩色图像灰度化
image_rgb2gray u_image_rgb2gray (
.clk (clk),
.reset (reset),
.valid_i (valid_i),
.img_data_i(img_data_i),
.valid_o (valid_gray),
.img_data_o(img_data_gray)
);
///高斯滤波
image_gaussian_filter u_image_gaussian_filter (
.clk (clk),
.reset (reset),
.img_width (img_width),
.img_height(img_height),
.valid_i (valid_gray),
.img_data_i(img_data_gray),
.valid_o (valid_gf),
.img_data_o(img_data_gf)
);
///Sobel算子
image_sobel_edge u_image_sobel_edge (
.clk (clk),
.reset (reset),
.img_width (img_width),
.img_height(img_height),
.valid_i (valid_gf),
.img_data_i(img_data_gf),
.valid_o (valid_sbl),
.grad_mag (grad_mag),
.grad_dx (grad_dx),
.grad_dy (grad_dy)
);
///非极大值计算
non_maximum_suppression u_non_maximum_suppression (
.clk (clk),
.reset (reset),
.img_width (img_width),
.img_height(img_height),
.valid_i (valid_sbl),
.grad_mag (grad_mag),
.grad_dx (grad_dx),
.grad_dy (grad_dy),
.valid_o (valid_nms),
.img_data_o(img_data_nms)
);
双阈值
//根据输入的低阈值和高阈值来判断,如果这个像素点大于高阈值,则赋值为255;如果低于低阈值,则赋值为0;
double_threshold u_double_threshold (
.clk (clk),
.reset (reset),
.img_width (img_width),
.img_height (img_height),
.low_threshold (low_threshold),
.high_threshold(high_threshold),
.valid_i (valid_nms),
.img_data_i (img_data_nms),
.valid_o (valid_db),
.img_data_o (img_data_db)
);
assign valid_o = valid_db;
assign img_data_o = {3{img_data_db}};
endmodule
2 彩色图变灰度图代码
`timescale 1ns / 1ps
//彩色图像灰度化
module image_rgb2gray (
input clk,
input reset,
input valid_i,
input [23:0] img_data_i,
output valid_o,
output [7:0] img_data_o
);
//常量
parameter MODE = 0; //0表示加权平均法,1表示平均法
//Y=0.299*R十0.587*G+0.114*B
parameter C0 = 9'd306; //0.299*1024;
parameter C1 = 10'd601; //0.587*1024;
parameter C2 = 7'd117; //0.114*1024;
//参数声明
wire [7:0] R, G, B;
assign {R, G, B} = img_data_i;
generate
if (MODE) begin
reg valid_d1;
reg [9:0] RGB_avr;
reg valid_d2;
reg [16:0] RGB_avr_m;
reg valid_d3;
reg [7:0] RGB_new;
//平均法
//1/3 * 512 = 171
always @(posedge clk) begin
if (reset) begin
valid_d1 <= 'b0;
RGB_avr <= 'b0;
end else begin
valid_d1 <= valid_i;
RGB_avr <= R + G + B;
end
end
//最大值不可能超过255*3*171 = 17'd130815
always @(posedge clk) begin
RGB_avr_m <= RGB_avr * 8'd171;
end
always @(posedge clk) begin
if (reset) begin
valid_d2 <= 'b0;
end else begin
valid_d2 <= valid_d1;
end
end
//最大值不可能超过255
always @(posedge clk) begin
if (reset) begin
valid_d3 <= 'b0;
RGB_new <= 'b0;
end else begin
valid_d3 <= valid_d2;
RGB_new <= RGB_avr_m[16:9];
end
end
assign valid_o = valid_d3;
assign img_data_o = {3{RGB_new}};
end else begin
//加权平均法
reg valid_d1;
reg [16:0] Y_R_m;
reg [17:0] Y_G_m;
reg [14:0] Y_B_m;
reg valid_d2;
reg [17:0] Y_s;//最大值,当RGB都等于255时,(C0 + C1 + C2)*255 = 1024*255;不会出现负数
reg valid_d3;
reg [7:0] Y;
always @(posedge clk) begin
Y_R_m <= R * C0;
Y_G_m <= G * C1;
Y_B_m <= B * C2;
end
always @(posedge clk) begin
if (reset) begin
valid_d1 <= 0;
end else begin
valid_d1 <= valid_i;
end
end
always @(posedge clk) begin
if (reset) begin
Y_s <= 0;
valid_d2 <= 0;
end else begin
if (valid_d1) begin
Y_s <= Y_R_m + Y_G_m + Y_B_m;
end
valid_d2 <= valid_d1;
end
end
always @(posedge clk) begin
if (reset) begin
Y <= 0;
valid_d3 <= 0;
end else begin
if (valid_d2) begin
Y <= Y_s[17:10];
end
valid_d3 <= valid_d2;
end
end
assign valid_o = valid_d3;
assign img_data_o = Y;
end
endgenerate
endmodule
3 3行缓存代码
`timescale 1ns / 1ps
//FIFO实现3行图像缓存
module image_line_buffer #(
parameter W = 8
) (
input wire clk,
input wire reset,
input wire [10:0] img_width,
input wire [ 9:0] img_height,
input wire valid_i,
input wire [W-1:0] img_data_i,
output reg valid_o,
output reg [W-1:0] prev_line_data_o,
output reg [W-1:0] cur_line_data_o,
output reg [W-1:0] next_line_data_o
);
//常量声明
localparam N = 3; //窗口大小
//变量声明
genvar i;
integer j;
wire [0:0] valid[0:N-1];
wire [W-1:0] data[0:N-1];
reg [10:0] out_data_cnt;
reg [9:0] out_line_cnt;
reg ch_valid;
reg [W-1:0] ch_data[0:N-1];
assign valid[0] = valid_i;
assign data[0] = img_data_i;
//行缓存模块, 只需要缓存N-1个fifo即可
generate
for (i = 1; i < N; i = i + 1) begin : lb
line_buffer #(
.W(W)
) u_line_buffer (
.clk (clk),
.reset (reset),
.img_width(img_width),
.valid_i (valid[i-1]),
.data_i (data[i-1]),
.valid_o (valid[i]),
.data_o (data[i])
);
end
endgenerate
//模式1,按照上一行、当前行、下一行输出
//特殊情况,可根据需求设定,是复制还是给0
//第1个行缓存,是整个画面的第1行时, 上一行数据不存在,复制第1个行缓存或者直接为0输出
//第1个行缓存,是整个画面的最后1行时,下一行数据不存在,复制第1个行缓存输出
always @(posedge clk) begin
if (reset) begin
for (j = 0; j < 3; j = j + 1) ch_data[j] <= 0;
end else if (valid[N-2]) begin
ch_data[1] <= data[1];
if (out_line_cnt == 0) begin
ch_data[2] <= 0;
ch_data[0] <= data[0];
end else if (out_line_cnt == img_height - 1) begin
ch_data[2] <= data[2];
ch_data[0] <= 0;
end else begin
ch_data[2] <= data[2];
ch_data[0] <= data[0];
end
end
end
always @(posedge clk) begin
if (reset) begin
ch_valid <= 0;
out_data_cnt <= 0;
out_line_cnt <= 0;
end else begin
ch_valid <= valid[N-2];
out_data_cnt <= valid[N-2] ? ((out_data_cnt == img_width - 1) ? 0 : out_data_cnt + 1) : out_data_cnt;
out_line_cnt <= valid[N-2]&&(out_data_cnt == img_width - 1) ? ((out_line_cnt == img_height - 1) ? 0 : out_line_cnt + 1) : out_line_cnt;
end
end
//单路输出
always @(posedge clk) begin
if (reset) begin
valid_o <= 0;
prev_line_data_o <= 0;
cur_line_data_o <= 0;
next_line_data_o <= 0;
end else begin
valid_o <= ch_valid;
prev_line_data_o <= ch_data[2];
cur_line_data_o <= ch_data[1];
next_line_data_o <= ch_data[0];
end
end
endmodule
4 1行缓存代码
`timescale 1ns / 1ps
//FIFO实现1行图像缓存
module line_buffer #(
parameter W = 8
) (
input wire clk,
input wire reset,
input wire [10:0] img_width,
input wire valid_i,
input wire [W-1:0] data_i,
output wire valid_o,
output wire [W-1:0] data_o
);
//变量声明
reg [10:0] wr_data_cnt;
wire rd_en;
wire [11:0] fifo_data_count_w;
//写入数据计数
always @(posedge clk or posedge reset) begin
if (reset) begin
wr_data_cnt <= 0;
end else begin
wr_data_cnt <= valid_i && (wr_data_cnt < img_width) ? (wr_data_cnt + 1'b1) : wr_data_cnt;
end
end
//assign rd_en = valid_i&&(wr_data_cnt == img_width) ? 1'b1 : 1'b0;
//等价于
assign rd_en = valid_i && (fifo_data_count_w == img_width) ? 1'b1 : 1'b0;
assign valid_o = rd_en;
generate
if (W == 8) begin
fifo_line_buffer_w8 u_fifo_line_buffer_w8 (
.clk (clk), // input wire clk
.srst (reset), // input wire srst
.din (data_i), // input wire [7 : 0] din
.wr_en (valid_i), // input wire wr_en
.rd_en (rd_en), // input wire rd_en
.dout (data_o), // output wire [7 : 0] dout
.full (), // output wire full
.empty (), // output wire empty
.data_count(fifo_data_count_w) // output wire [11 : 0] data_count
);
end else begin
fifo_line_buffer u_fifo_line_buffer (
.clk (clk), // input wire clk
.srst (reset), // input wire srst
.din (data_i), // input wire [22 : 0] din
.wr_en (valid_i), // input wire wr_en
.rd_en (rd_en), // input wire rd_en
.dout (data_o), // output wire [22 : 0] dout
.full (), // output wire full
.empty (), // output wire empty
.data_count(fifo_data_count_w) // output wire [11 : 0] data_count
);
end
endgenerate
endmodule
5 高斯滤波代码
`timescale 1ns / 1ps
// 高斯滤波
module image_gaussian_filter (
input wire clk,
input wire reset,
input wire [10:0] img_width,
input wire [ 9:0] img_height,
input wire valid_i,
input wire [7:0] img_data_i,
output reg valid_o,
output reg [7:0] img_data_o
);
//常量声明
localparam MODE = 1; //0表示彩色图像输出,1表示灰度图像输出
//变量声明
wire valid;
wire [7:0] prev_line_data;
wire [7:0] cur_line_data;
wire [7:0] next_line_data;
reg valid_d1;
reg [7:0] prev_line_data_d1;
reg [7:0] cur_line_data_d1;
reg [7:0] next_line_data_d1;
reg [7:0] prev_line_data_d2;
reg [7:0] cur_line_data_d2;
reg [7:0] next_line_data_d2;
reg [7:0] x_cnt;
reg valid_s;
reg [7:0] prev_line_data_d2_s;
reg [7:0] cur_line_data_d2_s;
reg [7:0] next_line_data_d2_s;
reg [7:0] prev_line_data_d1_s;
reg [7:0] cur_line_data_d1_s;
reg [7:0] next_line_data_d1_s;
reg [7:0] prev_line_data_s;
reg [7:0] cur_line_data_s;
reg [7:0] next_line_data_s;
wire [7:0] Y0, Y1, Y2;
wire [7:0] Y3, Y4, Y5;
wire [7:0] Y6, Y7, Y8;
reg valid_s_d1;
reg [9:0] Y_sum0;
reg [10:0] Y_sum1;
reg [9:0] Y_sum2;
reg valid_s_d2;
reg [14:0] Y_sum;
wire [15:0] RGB_sum;
wire [7:0] gray;
image_line_buffer u_image_line_buffer (
.clk (clk),
.reset (reset),
.img_width (img_width),
.img_height (img_height),
.valid_i (valid_i),
.img_data_i (img_data_i),
.valid_o (valid),
.prev_line_data_o(prev_line_data),
.cur_line_data_o (cur_line_data),
.next_line_data_o(next_line_data)
);
always @(posedge clk) begin
if (reset) begin
valid_d1 <= 0;
prev_line_data_d1 <= 0;
cur_line_data_d1 <= 0;
next_line_data_d1 <= 0;
prev_line_data_d2 <= 0;
cur_line_data_d2 <= 0;
next_line_data_d2 <= 0;
end else begin
valid_d1 <= valid;
prev_line_data_d1 <= prev_line_data;
cur_line_data_d1 <= cur_line_data;
next_line_data_d1 <= next_line_data;
prev_line_data_d2 <= prev_line_data_d1;
cur_line_data_d2 <= cur_line_data_d1;
next_line_data_d2 <= next_line_data_d1;
end
end
//边界数据处理
always @(posedge clk) begin
if (reset) begin
x_cnt <= 0;
end else begin
x_cnt <= valid_d1 ? ((x_cnt == img_width - 1) ? 0 : x_cnt + 1) : x_cnt;
end
end
always @(posedge clk) begin
if (reset) begin
valid_s <= 0;
prev_line_data_d2_s <= 0;
cur_line_data_d2_s <= 0;
next_line_data_d2_s <= 0;
prev_line_data_d1_s <= 0;
cur_line_data_d1_s <= 0;
next_line_data_d1_s <= 0;
prev_line_data_s <= 0;
cur_line_data_s <= 0;
next_line_data_s <= 0;
end else begin
valid_s <= valid_d1;
prev_line_data_d1_s <= prev_line_data_d1;
cur_line_data_d1_s <= cur_line_data_d1;
next_line_data_d1_s <= next_line_data_d1;
if (x_cnt == 0) begin
prev_line_data_d2_s <= prev_line_data_d1;
cur_line_data_d2_s <= cur_line_data_d1;
next_line_data_d2_s <= next_line_data_d1;
prev_line_data_s <= prev_line_data;
cur_line_data_s <= cur_line_data;
next_line_data_s <= next_line_data;
end
if (x_cnt == img_width - 1) begin
prev_line_data_d2_s <= prev_line_data_d2;
cur_line_data_d2_s <= cur_line_data_d2;
next_line_data_d2_s <= next_line_data_d2;
prev_line_data_s <= prev_line_data_d1;
cur_line_data_s <= cur_line_data_d1;
next_line_data_s <= next_line_data_d1;
end else begin
prev_line_data_d2_s <= prev_line_data_d2;
cur_line_data_d2_s <= cur_line_data_d2;
next_line_data_d2_s <= next_line_data_d2;
prev_line_data_s <= prev_line_data;
cur_line_data_s <= cur_line_data;
next_line_data_s <= next_line_data;
end
end
end
assign Y0 = prev_line_data_d2_s;
assign Y1 = cur_line_data_d2_s;
assign Y2 = next_line_data_d2_s;
assign Y3 = prev_line_data_d1_s;
assign Y4 = cur_line_data_d1_s;
assign Y5 = next_line_data_d1_s;
assign Y6 = prev_line_data_s;
assign Y7 = cur_line_data_s;
assign Y8 = next_line_data_s;
//高斯滤波模版
/************
[1. 2. 1.]
[2. 4. 2.]
[1. 2. 1.]
*************/
always @(posedge clk) begin
if (reset) begin
valid_s_d1 <= 0;
{Y_sum0, Y_sum1, Y_sum2} <= 0;
end else if (valid_s) begin
valid_s_d1 <= 1;
Y_sum0 <= Y0 + {Y1, 1'b0} + Y2;
Y_sum1 <= {Y3, 1'b0} + {Y4, 2'b0} + {Y5, 1'b0};
Y_sum2 <= Y6 + {Y7, 1'b0} + Y8;
end else valid_s_d1 <= 0;
end
//彩色图像 直接求和
//灰度图像 1/3,扩大4bit,即16/3约等于5 = 4 + 1
always @(posedge clk) begin
if (reset) begin
valid_s_d2 <= 0;
Y_sum <= 0;
end else if (valid_s_d1) begin
valid_s_d2 <= 1;
Y_sum <= Y_sum0 + Y_sum1 + Y_sum2;
end else valid_s_d2 <= 0;
end
always @(posedge clk) begin
if (reset) begin
valid_o <= 0;
img_data_o <= 0;
end else if (valid_s_d2) begin
valid_o <= 1;
img_data_o <= Y_sum[11:4];
end else begin
valid_o <= 0;
end
end
endmodule
6 sobel边缘检测代码
`timescale 1ns / 1ps
//边缘检测一阶微分算子:Sobel算子
module image_sobel_edge (
input wire clk,
input wire reset,
input wire [10:0] img_width,
input wire [ 9:0] img_height,
input wire valid_i,
input wire [7:0] img_data_i,
output reg valid_o,
output reg [7:0] grad_mag,
output reg [10:0] grad_dx,
output reg [10:0] grad_dy
);
//常量声明
localparam N = 16;
//变量声明
wire valid;
wire [7:0] prev_line_data;
wire [7:0] cur_line_data;
wire [7:0] next_line_data;
reg valid_d1;
reg [7:0] prev_line_data_d1;
reg [7:0] cur_line_data_d1;
reg [7:0] next_line_data_d1;
reg [7:0] prev_line_data_d2;
reg [7:0] cur_line_data_d2;
reg [7:0] next_line_data_d2;
reg [10:0] x_cnt;
reg valid_s;
reg [7:0] prev_line_data_d2_s;
reg [7:0] cur_line_data_d2_s;
reg [7:0] next_line_data_d2_s;
reg [7:0] prev_line_data_d1_s;
reg [7:0] cur_line_data_d1_s;
reg [7:0] next_line_data_d1_s;
reg [7:0] prev_line_data_s;
reg [7:0] cur_line_data_s;
reg [7:0] next_line_data_s;
wire [7:0] Y0;
wire [7:0] Y1;
wire [7:0] Y2;
wire [7:0] Y3;
wire [7:0] Y4;
wire [7:0] Y5;
wire [7:0] Y6;
wire [7:0] Y7;
wire [7:0] Y8;
reg valid_s_d1;
wire [9:0] Gx_Y0_a;
wire [9:0] Gx_Y1_a;
wire [9:0] Gy_Y0_a;
wire [9:0] Gy_Y1_a;
reg Gx_Y_sign;
reg [9:0] Gx_Y;
reg Gy_Y_sign;
reg [9:0] Gy_Y;
reg valid_s_d2;
reg Gx_Y_sign_d1;
reg [19:0] Gx_Y_square;
reg Gy_Y_sign_d1;
reg [19:0] Gy_Y_square;
wire [20:0] Gx_Gy_sum;
reg [N-1:0] Gx_Y_sign_shift;
reg [10*N-1:0] Gx_Y_shift;
reg [N-1:0] Gy_Y_sign_shift;
reg [10*N-1:0] Gy_Y_shift;
wire valid_sqr;
wire [10:0] data_sqr;
image_line_buffer u_image_line_buffer (
.clk (clk),
.reset (reset),
.img_width (img_width),
.img_height (img_height),
.valid_i (valid_i),
.img_data_i (img_data_i),
.valid_o (valid),
.prev_line_data_o(prev_line_data),
.cur_line_data_o (cur_line_data),
.next_line_data_o(next_line_data)
);
always @(posedge clk) begin
if (reset) begin
valid_d1 <= 0;
prev_line_data_d1 <= 0;
cur_line_data_d1 <= 0;
next_line_data_d1 <= 0;
prev_line_data_d2 <= 0;
cur_line_data_d2 <= 0;
next_line_data_d2 <= 0;
end else begin
valid_d1 <= valid;
prev_line_data_d1 <= prev_line_data;
cur_line_data_d1 <= cur_line_data;
next_line_data_d1 <= next_line_data;
prev_line_data_d2 <= prev_line_data_d1;
cur_line_data_d2 <= cur_line_data_d1;
next_line_data_d2 <= next_line_data_d1;
end
end
//边界数据处理
always @(posedge clk) begin
if (reset) begin
x_cnt <= 0;
end else begin
x_cnt <= valid_d1 ? ((x_cnt == img_width - 1) ? 0 : x_cnt + 1) : x_cnt;
end
end
always @(posedge clk) begin
if (reset) begin
valid_s <= 0;
prev_line_data_d2_s <= 0;
cur_line_data_d2_s <= 0;
next_line_data_d2_s <= 0;
prev_line_data_d1_s <= 0;
cur_line_data_d1_s <= 0;
next_line_data_d1_s <= 0;
prev_line_data_s <= 0;
cur_line_data_s <= 0;
next_line_data_s <= 0;
end else begin
valid_s <= valid_d1;
prev_line_data_d1_s <= prev_line_data_d1;
cur_line_data_d1_s <= cur_line_data_d1;
next_line_data_d1_s <= next_line_data_d1;
if (x_cnt == 0) begin
prev_line_data_d2_s <= prev_line_data_d1;
cur_line_data_d2_s <= cur_line_data_d1;
next_line_data_d2_s <= next_line_data_d1;
prev_line_data_s <= prev_line_data;
cur_line_data_s <= cur_line_data;
next_line_data_s <= next_line_data;
end
if (x_cnt == img_width - 1) begin
prev_line_data_d2_s <= prev_line_data_d2;
cur_line_data_d2_s <= cur_line_data_d2;
next_line_data_d2_s <= next_line_data_d2;
prev_line_data_s <= prev_line_data_d1;
cur_line_data_s <= cur_line_data_d1;
next_line_data_s <= next_line_data_d1;
end else begin
prev_line_data_d2_s <= prev_line_data_d2;
cur_line_data_d2_s <= cur_line_data_d2;
next_line_data_d2_s <= next_line_data_d2;
prev_line_data_s <= prev_line_data;
cur_line_data_s <= cur_line_data;
next_line_data_s <= next_line_data;
end
end
end
assign Y0 = prev_line_data_d2_s;
assign Y1 = cur_line_data_d2_s;
assign Y2 = next_line_data_d2_s;
assign Y3 = prev_line_data_d1_s;
assign Y4 = cur_line_data_d1_s;
assign Y5 = next_line_data_d1_s;
assign Y6 = prev_line_data_s;
assign Y7 = cur_line_data_s;
assign Y8 = next_line_data_s;
/Sobey算子
/************
[-1. 0. 1]
[-2. 0. 2]
Gx= [-1. 0. 1]
[ 1. 2. 1]
[ 0. 0. 0]
Gy= [-1. -2. -1]
*************/
assign Gx_Y0_a = Y0 + {Y3, 1'b0} + Y6;
assign Gx_Y1_a = Y2 + {Y5, 1'b0} + Y8;
assign Gy_Y0_a = Y0 + {Y1, 1'b0} + Y2;
assign Gy_Y1_a = Y6 + {Y7, 1'b0} + Y8;
always @(posedge clk) begin
if (reset) begin
valid_s_d1 <= 0;
{Gx_Y, Gy_Y} <= 0;
{Gx_Y_sign, Gy_Y_sign} <= 0;
end else if (valid_s) begin
valid_s_d1 <= 1;
Gx_Y <= (Gx_Y0_a > Gx_Y1_a) ? Gx_Y0_a - Gx_Y1_a : Gx_Y1_a - Gx_Y0_a;
Gx_Y_sign <= (Gx_Y0_a > Gx_Y1_a) ? 1 : 0;
Gy_Y <= (Gy_Y0_a > Gy_Y1_a) ? Gy_Y0_a - Gy_Y1_a : Gy_Y1_a - Gy_Y0_a;
Gy_Y_sign <= (Gy_Y0_a > Gy_Y1_a) ? 1 : 0;
end else valid_s_d1 <= 0;
end
//求平方
always @(posedge clk) begin
if (reset) begin
valid_s_d2 <= 0;
Gx_Y_square <= 0;
Gy_Y_square <= 0;
end else begin
valid_s_d2 <= valid_s_d1;
Gx_Y_square <= Gx_Y * Gx_Y;
Gy_Y_square <= Gy_Y * Gy_Y;
end
end
assign Gx_Gy_sum = Gx_Y_square + Gy_Y_square;
//平方根
cordic_square_root u_cordic_square_root (
.aclk (clk), // input wire aclk
.s_axis_cartesian_tvalid(valid_s_d2), // input wire s_axis_cartesian_tvalid
.s_axis_cartesian_tdata (Gx_Gy_sum), // input wire [23 : 0] s_axis_cartesian_tdata
.m_axis_dout_tvalid (valid_sqr), // output wire m_axis_dout_tvalid
.m_axis_dout_tdata (data_sqr) // output wire [15 : 0] m_axis_dout_tdata
);
always @(posedge clk) begin
if (reset) begin
Gx_Y_sign_shift <= 0;
Gx_Y_shift <= 0;
Gy_Y_sign_shift <= 0;
Gy_Y_shift <= 0;
end else begin
Gx_Y_sign_shift <= {Gx_Y_sign_shift, Gx_Y_sign};
Gx_Y_shift <= {Gx_Y_shift, Gx_Y};
Gy_Y_sign_shift <= {Gy_Y_sign_shift, Gy_Y_sign};
Gy_Y_shift <= {Gy_Y_shift, Gy_Y};
end
end
always @(posedge clk) begin
if (reset) begin
valid_o <= 0;
grad_mag <= 0;
grad_dx <= 0;
grad_dy <= 0;
end else if (valid_sqr) begin
valid_o <= 1;
grad_mag <= data_sqr;
grad_dx <= {Gx_Y_sign_shift[N-1], Gx_Y_shift[N*10-1:(N-1)*10]};
grad_dy <= {Gy_Y_sign_shift[N-1], Gy_Y_shift[N*10-1:(N-1)*10]};
end else begin
valid_o <= 0;
end
end
endmodule
7 非极大值抑制代码
`timescale 1ns / 1ps
// 非极大值抑制
module non_maximum_suppression (
input clk,
input reset,
input wire [10:0] img_width,
input wire [ 9:0] img_height,
input valid_i,
input [7:0] grad_mag,
input [10:0] grad_dx,
input [10:0] grad_dy,
output reg valid_o,
output reg [7:0] img_data_o
);
//常量
localparam N = 24;
//参数声明
wire valid;
wire [7:0] prev_line_data;
wire [7:0] cur_line_data;
wire [7:0] next_line_data;
reg valid_d1;
reg [7:0] prev_line_data_d1;
reg [7:0] cur_line_data_d1;
reg [7:0] next_line_data_d1;
reg [7:0] prev_line_data_d2;
reg [7:0] cur_line_data_d2;
reg [7:0] next_line_data_d2;
reg [10:0] x_cnt;
reg valid_s;
reg [7:0] prev_line_data_d2_s;
reg [7:0] cur_line_data_d2_s;
reg [7:0] next_line_data_d2_s;
reg [7:0] prev_line_data_d1_s;
reg [7:0] cur_line_data_d1_s;
reg [7:0] next_line_data_d1_s;
reg [7:0] prev_line_data_s;
reg [7:0] cur_line_data_s;
reg [7:0] next_line_data_s;
wire [7:0] Y0, Y1, Y2;
wire [7:0] Y3, Y4, Y5;
wire [7:0] Y6, Y7, Y8;
wire grad_valid;
wire [21:0] grad_cur_line_data;
reg valid_s_d1;
reg grad_dx_sign;
reg [9:0] grad_dx_abs;
reg grad_dy_sign;
reg [9:0] grad_dy_abs;
reg [1:0] mode;
reg [9:0] dividend, divisor;
wire div_valid;
wire [23:0] div_data;
reg [2*N-1:0] mode_shift;
wire mode_s;
reg [72*N-1:0] Y_shift;
wire [7:0] Y0_s, Y1_s, Y2_s;
wire [7:0] Y3_s, Y4_s, Y5_s;
wire [7:0] Y6_s, Y7_s, Y8_s;
reg div_valid_d1;
reg [7:0] grad1, grad2, grad3, grad4;
reg [7:0] weight;
reg [8:0] one_sub_weight;
reg [7:0] Y4_s_d1;
reg div_valid_d2;
reg [15:0] grad1_m, grad2_m;
reg [16:0] grad3_m, grad4_m;
reg [7:0] Y4_s_d2;
wire [16:0] t1, t2;
/行视频数据缓存
image_line_buffer u_image_line_buffer (
.clk (clk),
.reset (reset),
.img_width (img_width),
.img_height (img_height),
.valid_i (valid_i),
.img_data_i (grad_mag),
.valid_o (valid),
.prev_line_data_o(prev_line_data),
.cur_line_data_o (cur_line_data),
.next_line_data_o(next_line_data)
);
always @(posedge clk) begin
if (reset) begin
valid_d1 <= 0;
prev_line_data_d1 <= 0;
cur_line_data_d1 <= 0;
next_line_data_d1 <= 0;
prev_line_data_d2 <= 0;
cur_line_data_d2 <= 0;
next_line_data_d2 <= 0;
end else begin
valid_d1 <= valid;
prev_line_data_d1 <= prev_line_data;
cur_line_data_d1 <= cur_line_data;
next_line_data_d1 <= next_line_data;
prev_line_data_d2 <= prev_line_data_d1;
cur_line_data_d2 <= cur_line_data_d1;
next_line_data_d2 <= next_line_data_d1;
end
end
//边界数据处理
always @(posedge clk) begin
if (reset) begin
x_cnt <= 0;
end else begin
x_cnt <= valid_d1 ? ((x_cnt == img_width - 1) ? 0 : x_cnt + 1) : x_cnt;
end
end
always @(posedge clk) begin
if (reset) begin
valid_s <= 0;
prev_line_data_d2_s <= 0;
cur_line_data_d2_s <= 0;
next_line_data_d2_s <= 0;
prev_line_data_d1_s <= 0;
cur_line_data_d1_s <= 0;
next_line_data_d1_s <= 0;
prev_line_data_s <= 0;
cur_line_data_s <= 0;
next_line_data_s <= 0;
end else begin
valid_s <= valid_d1;
prev_line_data_d1_s <= prev_line_data_d1;
cur_line_data_d1_s <= cur_line_data_d1;
next_line_data_d1_s <= next_line_data_d1;
if (x_cnt == 0) begin
prev_line_data_d2_s <= prev_line_data_d1;
cur_line_data_d2_s <= cur_line_data_d1;
next_line_data_d2_s <= next_line_data_d1;
prev_line_data_s <= prev_line_data;
cur_line_data_s <= cur_line_data;
next_line_data_s <= next_line_data;
end
if (x_cnt == img_width - 1) begin
prev_line_data_d2_s <= prev_line_data_d2;
cur_line_data_d2_s <= cur_line_data_d2;
next_line_data_d2_s <= next_line_data_d2;
prev_line_data_s <= prev_line_data_d1;
cur_line_data_s <= cur_line_data_d1;
next_line_data_s <= next_line_data_d1;
end else begin
prev_line_data_d2_s <= prev_line_data_d2;
cur_line_data_d2_s <= cur_line_data_d2;
next_line_data_d2_s <= next_line_data_d2;
prev_line_data_s <= prev_line_data;
cur_line_data_s <= cur_line_data;
next_line_data_s <= next_line_data;
end
end
end
assign Y0 = prev_line_data_d2_s;
assign Y1 = cur_line_data_d2_s;
assign Y2 = next_line_data_d2_s;
assign Y3 = prev_line_data_d1_s;
assign Y4 = cur_line_data_d1_s;
assign Y5 = next_line_data_d1_s;
assign Y6 = prev_line_data_s;
assign Y7 = cur_line_data_s;
assign Y8 = next_line_data_s;
/grad_dx和grad_dy行数据缓存
image_line_buffer #(
.W(21)
) u_image_grad_line_buffer (
.clk (clk),
.reset (reset),
.img_width (img_width),
.img_height (img_height),
.valid_i (valid_i),
.img_data_i ({grad_dx, grad_dy}),
.valid_o (grad_valid),
.prev_line_data_o(),
.cur_line_data_o (grad_cur_line_data),
.next_line_data_o()
);
/非极大值限制计算
//计算grad_dx,grad_dy绝对值
always @(posedge clk) begin
if (reset) begin
{grad_dx_sign, grad_dx_abs} <= 0;
{grad_dy_sign, grad_dy_abs} <= 0;
end else begin
grad_dx_sign <= grad_cur_line_data[21];
grad_dx_abs <= grad_cur_line_data[20:11];
grad_dy_sign <= grad_cur_line_data[10];
grad_dy_abs <= grad_cur_line_data[9:0];
end
end
//计算模式
always @(posedge clk) begin
if (reset) begin
mode <= 0;
{dividend, divisor} <= 0;
end else begin
if (grad_dx_abs > grad_dy_abs) begin
mode <= (grad_dx_sign ^ grad_dy_sign) ? 0 : 1;
dividend <= grad_dy_abs;
divisor <= grad_dx_abs;
end else begin
mode <= (grad_dx_sign ^ grad_dy_sign) ? 2 : 3;
dividend <= grad_dx_abs;
divisor <= grad_dy_abs;
end
end
end
//除法计算
div_gen_10x10 u_div_gen_10x10 (
.aclk (clk), // input wire aclk
.s_axis_divisor_tvalid (valid_s), // input wire s_axis_divisor_tvalid
.s_axis_divisor_tdata ({6'b0, divisor}), // input wire [15 : 0] s_axis_divisor_tdata
.s_axis_dividend_tvalid(valid_s), // input wire s_axis_dividend_tvalid
.s_axis_dividend_tdata ({6'b0, dividend}), // input wire [15 : 0] s_axis_dividend_tdata
.m_axis_dout_tvalid (div_valid), // output wire m_axis_dout_tvalid
.m_axis_dout_tdata (div_data) // output wire [23 : 0] m_axis_dout_tdata
);
//同步延时
always @(posedge clk) begin
if (reset) begin
mode_shift <= 0;
Y_shift <= 0;
end else begin
mode_shift <= {mode_shift, mode};
Y_shift <= {Y_shift, Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8};
end
end
assign mode_s = mode_shift[2*N-1:2*(N-1)];
assign {Y0_s, Y1_s, Y2_s, Y3_s, Y4_s, Y5_s, Y6_s, Y7_s, Y8_s} = Y_shift[72*N-1:72*(N-1)];
//计算插值系数、插值数据
always @(posedge clk) begin
if (reset) begin
div_valid_d1 <= 0;
weight <= 0;
one_sub_weight <= 0;
Y4_s_d1 <= 0;
{grad1, grad2, grad3, grad4} <= 0;
end else begin
div_valid_d1 <= div_valid;
weight <= div_data[7:0];
one_sub_weight <= 256 - div_data[7:0];
Y4_s_d1 <= Y4_s;
case (mode_s)
0: begin
grad1 <= Y7_s;
grad2 <= Y1_s;
grad3 <= Y8_s;
grad4 <= Y0_s;
end
1: begin
grad1 <= Y7_s;
grad2 <= Y1_s;
grad3 <= Y6_s;
grad4 <= Y2_s;
end
2: begin
grad1 <= Y5_s;
grad2 <= Y3_s;
grad3 <= Y8_s;
grad4 <= Y0_s;
end
3: begin
grad1 <= Y5_s;
grad2 <= Y3_s;
grad3 <= Y6_s;
grad4 <= Y2_s;
end
endcase
end
end
//计算极值t1\t2
always @(posedge clk) begin
if (reset) begin
div_valid_d2 <= 0;
Y4_s_d2 <= 0;
{grad1_m, grad2_m, grad3_m, grad4_m} <= 0;
end else begin
div_valid_d2 <= div_valid_d1;
Y4_s_d2 <= Y4_s_d1;
grad1_m <= grad1 * weight;
grad2_m <= grad2 * weight;
grad3_m <= grad3 * one_sub_weight;
grad4_m <= grad4 * one_sub_weight;
end
end
assign t1 = grad1_m + grad3_m;
assign t2 = grad2_m + grad4_m;
//超过极值后,赋值为0
always @(posedge clk) begin
if (reset) begin
valid_o <= 0;
img_data_o <= 0;
end else if (div_valid_d2) begin
valid_o <= 1;
img_data_o <= ({1'b0, Y4_s_d2} > t1[16:8]) && ({1'b0, Y4_s_d2} > t2[16:8]) ? Y4_s_d2 : 0;
end else begin
valid_o <= 0;
end
end
endmodule
8 双阈值代码
`timescale 1ns / 1ps
//双阈值
module double_threshold (
input clk,
input reset,
input [10:0] img_width,
input [ 9:0] img_height,
input [ 7:0] low_threshold,
input [ 7:0] high_threshold,
input valid_i,
input [7:0] img_data_i,
output reg valid_o,
output reg [7:0] img_data_o
);
//常量声明
localparam MODE = 1; //0表示彩色图像输出,1表示灰度图像输出
//变量声明
wire valid;
wire [7:0] prev_line_data;
wire [7:0] cur_line_data;
wire [7:0] next_line_data;
reg valid_d1;
reg [7:0] prev_line_data_d1;
reg [7:0] cur_line_data_d1;
reg [7:0] next_line_data_d1;
reg [7:0] prev_line_data_d2;
reg [7:0] cur_line_data_d2;
reg [7:0] next_line_data_d2;
reg [7:0] x_cnt;
reg valid_s;
reg [7:0] prev_line_data_d2_s;
reg [7:0] cur_line_data_d2_s;
reg [7:0] next_line_data_d2_s;
reg [7:0] prev_line_data_d1_s;
reg [7:0] cur_line_data_d1_s;
reg [7:0] next_line_data_d1_s;
reg [7:0] prev_line_data_s;
reg [7:0] cur_line_data_s;
reg [7:0] next_line_data_s;
wire [7:0] Y0, Y1, Y2;
wire [7:0] Y3, Y4, Y5;
wire [7:0] Y6, Y7, Y8;
image_line_buffer u_image_line_buffer (
.clk (clk),
.reset (reset),
.img_width (img_width),
.img_height (img_height),
.valid_i (valid_i),
.img_data_i (img_data_i),
.valid_o (valid),
.prev_line_data_o(prev_line_data),
.cur_line_data_o (cur_line_data),
.next_line_data_o(next_line_data)
);
always @(posedge clk) begin
if (reset) begin
valid_d1 <= 0;
prev_line_data_d1 <= 0;
cur_line_data_d1 <= 0;
next_line_data_d1 <= 0;
prev_line_data_d2 <= 0;
cur_line_data_d2 <= 0;
next_line_data_d2 <= 0;
end else begin
valid_d1 <= valid;
prev_line_data_d1 <= prev_line_data;
cur_line_data_d1 <= cur_line_data;
next_line_data_d1 <= next_line_data;
prev_line_data_d2 <= prev_line_data_d1;
cur_line_data_d2 <= cur_line_data_d1;
next_line_data_d2 <= next_line_data_d1;
end
end
//边界数据处理
always @(posedge clk) begin
if (reset) begin
x_cnt <= 0;
end else begin
x_cnt <= valid_d1 ? ((x_cnt == img_width - 1) ? 0 : x_cnt + 1) : x_cnt;
end
end
always @(posedge clk) begin
if (reset) begin
valid_s <= 0;
prev_line_data_d2_s <= 0;
cur_line_data_d2_s <= 0;
next_line_data_d2_s <= 0;
prev_line_data_d1_s <= 0;
cur_line_data_d1_s <= 0;
next_line_data_d1_s <= 0;
prev_line_data_s <= 0;
cur_line_data_s <= 0;
next_line_data_s <= 0;
end else begin
valid_s <= valid_d1;
prev_line_data_d1_s <= prev_line_data_d1;
cur_line_data_d1_s <= cur_line_data_d1;
next_line_data_d1_s <= next_line_data_d1;
if (x_cnt == 0) begin
prev_line_data_d2_s <= prev_line_data_d1;
cur_line_data_d2_s <= cur_line_data_d1;
next_line_data_d2_s <= next_line_data_d1;
prev_line_data_s <= prev_line_data;
cur_line_data_s <= cur_line_data;
next_line_data_s <= next_line_data;
end
if (x_cnt == img_width - 1) begin
prev_line_data_d2_s <= prev_line_data_d2;
cur_line_data_d2_s <= cur_line_data_d2;
next_line_data_d2_s <= next_line_data_d2;
prev_line_data_s <= prev_line_data_d1;
cur_line_data_s <= cur_line_data_d1;
next_line_data_s <= next_line_data_d1;
end else begin
prev_line_data_d2_s <= prev_line_data_d2;
cur_line_data_d2_s <= cur_line_data_d2;
next_line_data_d2_s <= next_line_data_d2;
prev_line_data_s <= prev_line_data;
cur_line_data_s <= cur_line_data;
next_line_data_s <= next_line_data;
end
end
end
assign Y0 = prev_line_data_d2_s;
assign Y1 = cur_line_data_d2_s;
assign Y2 = next_line_data_d2_s;
assign Y3 = prev_line_data_d1_s;
assign Y4 = cur_line_data_d1_s;
assign Y5 = next_line_data_d1_s;
assign Y6 = prev_line_data_s;
assign Y7 = cur_line_data_s;
assign Y8 = next_line_data_s;
always @(posedge clk) begin
if (reset) begin
valid_o <= 0;
img_data_o <= 0;
end else if (valid_s) begin
valid_o <= 1;
if (Y4 < low_threshold) img_data_o <= 0;
else if((Y0 > high_threshold)||(Y1 > high_threshold)||(Y2 > high_threshold)||
(Y3 > high_threshold)||(Y4 > high_threshold)||(Y5 > high_threshold)||
(Y6 > high_threshold)||(Y7 > high_threshold)||(Y8 > high_threshold))
img_data_o <= 255;
else img_data_o <= 0;
end else begin
valid_o <= 0;
end
end
endmodule