├── And.v ├── Compare.v ├── Controller.v ├── Div_Clk.v ├── GetAddr.v ├── Or.v ├── README.md ├── Scan.v ├── YCrCb.v ├── YCrCb_tb.v ├── add_g.v ├── dilate.v ├── dilate_tb.v ├── erode.v ├── erode_tb.v ├── get_g.v ├── get_length.v ├── median_filter.v ├── median_filter_tb.v ├── sobel_detect.v ├── sobel_detect_tb.v └── threshold_detect.v /And.v: -------------------------------------------------------------------------------- 1 | module And( 2 | input clk, 3 | input rst, 4 | input data_0, 5 | input data_1, 6 | input data_2, 7 | output reg result); 8 | 9 | always @ (posedge clk) 10 | begin 11 | if(rst) 12 | result <= 0; 13 | else 14 | result <= (data_0 & data_1 & data_2); 15 | end 16 | 17 | endmodule -------------------------------------------------------------------------------- /Compare.v: -------------------------------------------------------------------------------- 1 | module Compare( 2 | input clk, 3 | input rst, 4 | input [7:0] data_1, 5 | input [7:0] data_2, 6 | input [7:0] data_3, 7 | output reg [7:0] data_min, 8 | output reg [7:0] data_middle, 9 | output reg [7:0] data_max); 10 | 11 | always @ (posedge clk or posedge rst) 12 | begin 13 | if(rst) 14 | begin 15 | data_max <= 0; 16 | data_min <= 0; 17 | data_middle <= 0; 18 | end 19 | 20 | else 21 | begin 22 | if(data_1 < data_2) 23 | begin 24 | if(data_2 < data_3) 25 | begin 26 | data_min <= data_1; 27 | data_middle <= data_2; 28 | data_max <= data_3; 29 | end 30 | 31 | else if(data_3 < data_1) 32 | begin 33 | data_min <= data_3; 34 | data_middle <= data_1; 35 | data_max <= data_2; 36 | end 37 | 38 | else 39 | begin 40 | data_min <= data_1; 41 | data_middle <= data_3; 42 | data_max <= data_2; 43 | end 44 | end 45 | 46 | else 47 | begin 48 | if(data_1 < data_3) 49 | begin 50 | data_min <= data_2; 51 | data_middle <= data_1; 52 | data_max <= data_3; 53 | end 54 | 55 | else if(data_3 < data_2) 56 | begin 57 | data_min <= data_3; 58 | data_middle <= data_2; 59 | data_max <= data_1; 60 | end 61 | 62 | else 63 | begin 64 | data_min <= data_2; 65 | data_middle <= data_3; 66 | data_max <= data_1; 67 | end 68 | end 69 | end 70 | end 71 | 72 | endmodule -------------------------------------------------------------------------------- /Controller.v: -------------------------------------------------------------------------------- 1 | module Controller( 2 | input clk, 3 | input rst, 4 | input [3:0] Edge, 5 | output [11:0] pixel, 6 | output hs, 7 | output vs 8 | ); 9 | 10 | parameter Hor_Blank_Time = 256; 11 | parameter Hor_Addr_Time = 800; 12 | parameter Hor_End_Time = Hor_Blank_Time + Hor_Addr_Time - 1; 13 | parameter Hor_Pic_End_Time = Hor_Blank_Time + (Hor_Addr_Time >> 1) - 1; 14 | 15 | parameter Ver_Blank_Time = 28; 16 | parameter Ver_Addr_Time = 600; 17 | parameter Ver_End_Time = Ver_Blank_Time + Ver_Addr_Time - 1; 18 | parameter Ver_Pic_End_Time = Ver_Blank_Time + (Ver_Addr_Time >> 1) - 1; 19 | 20 | wire [10:0] hcount, vcount; 21 | wire [15:0] douta; 22 | wire div_clk; 23 | wire [10:0] latency; 24 | 25 | assign latency = (Edge == 4'b0001 ? 6 : (Edge == 4'b0010 ? 9 : (Edge == 4'b0011 ? 13 : (Edge == 4'b0100 ? 15 : (Edge == 4'b0101 ? 17 : 3))))); 26 | 27 | Scan scan_dut( 28 | .rst(rst), 29 | .clk(div_clk), 30 | .hcount(hcount), 31 | .vcount(vcount), 32 | .hs(hs), 33 | .vs(vs)); 34 | 35 | wire [16:0] Addr; 36 | 37 | wire RealClk; 38 | wire enable; 39 | 40 | wire [10:0] RealVcount, RealHcount; 41 | wire [10:0] RealVcount1, RealHcount1; 42 | wire [10:0] RealVcount2, RealHcount2; 43 | wire [10:0] RealVcount3, RealHcount3; 44 | wire [10:0] RealVcount4, RealHcount4; 45 | wire [10:0] RealVcount5, RealHcount5; 46 | 47 | //当前hs和vs对应的显示块中的位置 48 | assign RealVcount = vcount - Ver_Blank_Time; 49 | assign RealHcount = hcount - Hor_Blank_Time + latency; 50 | 51 | assign RealVcount1 = (Edge >= 4'b0010 ? (RealVcount2 + 2) : RealVcount2); 52 | assign RealHcount1 = (Edge >= 4'b0010 ? (RealHcount2 + 2) : RealHcount2); 53 | 54 | assign RealVcount2 = (Edge >= 4'b0011 ? (RealVcount3 + 2) : RealVcount3); 55 | assign RealHcount2 = (Edge >= 4'b0011 ? (RealHcount3 + 2) : RealHcount3); 56 | 57 | assign RealVcount3 = (Edge >= 4'b0100 ? (RealVcount4 + 2) : RealVcount4); 58 | assign RealHcount3 = (Edge >= 4'b0100 ? (RealHcount4 + 2) : RealHcount4); 59 | 60 | assign RealVcount4 = (Edge >= 4'b0101 ? (RealVcount5 + 2) : RealVcount5); 61 | assign RealHcount4 = (Edge >= 4'b0101 ? (RealHcount5 + 2) : RealHcount5); 62 | 63 | assign RealVcount5 = RealVcount; 64 | assign RealHcount5 = RealHcount; 65 | 66 | assign enable = (vcount >= Ver_Blank_Time && vcount <= Ver_End_Time) && (hcount >= Hor_Blank_Time && hcount <= Hor_End_Time); 67 | //assign pic = (vcount >= Ver_Blank_Time && vcount <= Ver_Pic_End_Time) && (hcount >= Hor_Blank_Time && hcount <= Hor_Pic_End_Time); 68 | 69 | //计算 RealVcount1 �??? RealHcount1 对应的读出地�??? 70 | GetAddr get_addr_dut( 71 | .clk(div_clk), 72 | .rst(rst), 73 | .hcount(RealHcount1), 74 | .vcount(RealVcount1), 75 | .Addr(Addr)); 76 | 77 | //assign Addr = (RealHcount >> 1) + ((RealVcount >> 1) * 400); 78 | 79 | //assign Addr = pic ? (RealHcount + RealVcount * 400) : 0; 80 | 81 | //输出地址Addr对应的pixel_value 82 | blk_mem_gen_0 blk_dut_output_original( 83 | .clka(div_clk), // input wire clka 84 | .addra(Addr), // input wire [16 : 0] addra 85 | .douta(douta) // output wire [15 : 0] douta 86 | ); 87 | 88 | wire [7:0] Y; 89 | 90 | //计算对应pixel_value的灰�? 91 | YCrCb YCrCb_dut( 92 | .clk(div_clk), 93 | .rst(rst), 94 | .R(douta[15:11]), 95 | .G(douta[10:5]), 96 | .B(douta[4:0]), 97 | .Y(Y)); 98 | 99 | wire [7:0] median_filter_pixel_value; 100 | 101 | //计算对应灰度的做完中值滤波后的pixel_value 102 | median_filter median_filter_dut( 103 | .clk(div_clk), 104 | .rst(rst), 105 | .hcount(RealHcount2), 106 | .vcount(RealVcount2), 107 | .Y(Y), 108 | .pixel_value(median_filter_pixel_value) 109 | ); 110 | 111 | wire [11:0] sobel_value; 112 | 113 | sobel_detect sobel_detect_dut( 114 | .clk(div_clk), 115 | .rst(rst), 116 | .hcount(RealHcount3), 117 | .vcount(RealVcount3), 118 | .median_value(median_filter_pixel_value), 119 | .sobel_value(sobel_value)); 120 | 121 | wire [11:0] erode_value; 122 | 123 | erode erode_dut( 124 | .clk(div_clk), 125 | .rst(rst), 126 | .hcount(RealHcount4), 127 | .vcount(RealVcount4), 128 | .sobel_value(sobel_value[0]), 129 | .erode_value(erode_value)); 130 | 131 | wire [11:0] dilate_value; 132 | 133 | dilate dilate_dut( 134 | .clk(div_clk), 135 | .rst(rst), 136 | .hcount(RealHcount5), 137 | .vcount(RealVcount5), 138 | .erode_value(erode_value[0]), 139 | .dilate_value(dilate_value)); 140 | 141 | //VGA时序分频 142 | clk_wiz_0 divider_dut 143 | ( 144 | // Clock in ports 145 | .clk(clk), // input clk 146 | // Clock out ports 147 | .div_clk(div_clk), // output div_clk 148 | // Status and control signals 149 | .reset(rst)); // input reset 150 | 151 | //输出对应模式下的当前像素 152 | //assign pixel = enable ? (pic ? {douta[15:12], douta[10:7], douta[4:1]} : 12'b000000000000) : 12'b000100010001; 153 | assign pixel = enable ? 154 | (Edge == 4'b0001 ? 155 | {3{Y[7:4]}} 156 | :(Edge == 4'b0010 ? 157 | {3{median_filter_pixel_value[7:4]}} 158 | :(Edge == 4'b0011 ? 159 | sobel_value 160 | :(Edge == 4'b0100 ? 161 | erode_value 162 | :(Edge == 4'b0101 ? 163 | dilate_value 164 | :{douta[15:12], douta[10:7], douta[4:1]}))))) 165 | :12'b000100010001; 166 | 167 | endmodule 168 | 169 | -------------------------------------------------------------------------------- /Div_Clk.v: -------------------------------------------------------------------------------- 1 | module Divider ( 2 | input I_CLK, //输入时钟信号,上升沿有效 3 | input Rst, //同步复位信号,高电平有效 4 | output O_CLK //输出时钟信号,占空比 50%,先低电平后高电平 5 | ); 6 | parameter cycle = 4; 7 | integer cnt = 0; 8 | reg reg_O_CLK = 0; 9 | assign O_CLK = reg_O_CLK; 10 | always @ (posedge I_CLK) 11 | begin 12 | if(Rst == 1) 13 | begin 14 | cnt <= 0; 15 | reg_O_CLK <= 0; 16 | end 17 | else 18 | begin 19 | cnt = cnt + 1; 20 | if((cnt << 1) == cycle) 21 | begin 22 | reg_O_CLK = ~reg_O_CLK; 23 | cnt = 0; 24 | end 25 | 26 | end 27 | end 28 | 29 | endmodule -------------------------------------------------------------------------------- /GetAddr.v: -------------------------------------------------------------------------------- 1 | module GetAddr( 2 | input clk, 3 | input rst, 4 | input [10:0] hcount, 5 | input [10:0] vcount, 6 | output reg [16:0] Addr = 0 7 | ); 8 | reg [16:0] hcount1 = 0, vcount1 = 0, vcount2 = 0; 9 | always @ (posedge clk or posedge rst) 10 | begin 11 | if(rst) 12 | begin 13 | hcount1 <= 0; 14 | vcount1 <= 0; 15 | end 16 | else 17 | begin 18 | hcount1 <= (hcount >> 1); 19 | vcount1 <= (vcount >> 1); 20 | end 21 | end 22 | 23 | always @ (posedge clk or posedge rst) 24 | begin 25 | if(rst) 26 | vcount2 <= 0; 27 | else 28 | vcount2 <= vcount1 * 400; 29 | end 30 | 31 | always @ (posedge clk or posedge rst) 32 | begin 33 | if(rst) 34 | Addr <= 0; 35 | else 36 | Addr <= hcount1 + vcount2; 37 | end 38 | 39 | endmodule -------------------------------------------------------------------------------- /Or.v: -------------------------------------------------------------------------------- 1 | module Or( 2 | input clk, 3 | input rst, 4 | input data_0, 5 | input data_1, 6 | input data_2, 7 | output reg result); 8 | 9 | always @ (posedge clk) 10 | begin 11 | if(rst) 12 | result <= 0; 13 | else 14 | result <= (data_0 | data_1 | data_2); 15 | end 16 | 17 | endmodule -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FPGA-edge_detect 2 | Nexys 4 DDR Artix-7 3 |
ouput: VGA 4 |
use IP ROM to store picture (format: *.coe) 5 | * 1.Convert colored picture to gray picture 6 | * 2.Median filter to denoise 7 | * 3.Sobel detect 8 | * 4.erode and dilate 9 | -------------------------------------------------------------------------------- /Scan.v: -------------------------------------------------------------------------------- 1 | module Scan( 2 | input rst, 3 | input clk, 4 | output reg[10:0] hcount = 0, 5 | output reg[10:0] vcount = 0, 6 | output hs, 7 | output vs); 8 | 9 | parameter Hor_Sync_Time = 128; 10 | parameter Hor_Total_Time = 1056; 11 | parameter Ver_Sync_Time = 4; 12 | parameter Ver_Total_Time = 628; 13 | 14 | assign hs = (hcount < Hor_Sync_Time) ? 0 : 1; 15 | always @ (posedge clk or posedge rst) 16 | begin 17 | if(rst || hcount == Hor_Total_Time - 1) 18 | begin 19 | hcount <= 0; 20 | end 21 | else 22 | begin 23 | hcount <= hcount + 1; 24 | end 25 | end 26 | 27 | assign vs = (vcount < Ver_Sync_Time) ? 0 : 1; 28 | always @ (posedge clk or posedge rst) 29 | begin 30 | if(rst) 31 | begin 32 | vcount <= 0; 33 | end 34 | else if(hcount == Hor_Total_Time - 1) 35 | begin 36 | if(vcount == Ver_Total_Time - 1) 37 | begin 38 | vcount <= 0; 39 | end 40 | else 41 | begin 42 | vcount <= vcount + 1; 43 | end 44 | end 45 | end 46 | 47 | endmodule -------------------------------------------------------------------------------- /YCrCb.v: -------------------------------------------------------------------------------- 1 | module YCrCb( 2 | input clk, 3 | input rst, 4 | input [4:0] R, 5 | input [5:0] G, 6 | input [4:0] B, 7 | output [7:0] Y); 8 | 9 | wire [7:0] R0, G0, B0; 10 | assign R0 = {R, R[4:2]}; 11 | assign G0 = {G, G[5:4]}; 12 | assign B0 = {B, B[4:2]}; 13 | 14 | reg [15:0] R1, G1, B1; 15 | 16 | always @ (posedge clk or posedge rst) 17 | begin 18 | if(rst) 19 | begin 20 | R1 <= 0; 21 | G1 <= 0; 22 | B1 <= 0; 23 | 24 | end 25 | 26 | else 27 | begin 28 | R1 <= R0 * 77; 29 | G1 <= G0 * 150; 30 | B1 <= B0 * 29; 31 | end 32 | end 33 | 34 | reg [15:0] Y0; 35 | 36 | always @ (posedge clk or posedge rst) 37 | begin 38 | if(rst) 39 | begin 40 | Y0 <= 0; 41 | end 42 | 43 | else 44 | begin 45 | Y0 <= R1 + G1 + B1; 46 | end 47 | end 48 | 49 | assign Y = Y0[15:8]; 50 | 51 | endmodule -------------------------------------------------------------------------------- /YCrCb_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | module YCrCb_tb(); 3 | 4 | reg clk = 0; 5 | reg [4:0] R; 6 | reg [5:0] G; 7 | reg [4:0] B; 8 | wire [7:0] Y; 9 | 10 | integer i; 11 | integer j; 12 | integer k; 13 | 14 | initial 15 | begin 16 | for(i = 0; i <= 10; i = i + 1) 17 | for(j = 0; j <= 20; j = j + 1) 18 | for(k = 0; k <= 20; k = k + 1) 19 | begin 20 | R = i[4:0]; 21 | G = j[5:0]; 22 | B = k[4:0]; 23 | #2; 24 | clk = ~clk; 25 | end 26 | end 27 | 28 | YCrCb YCrCb_dut( 29 | .clk(clk), 30 | .rst(1'b0), 31 | .R(R), 32 | .G(G), 33 | .B(B), 34 | .Y(Y) 35 | ); 36 | 37 | endmodule -------------------------------------------------------------------------------- /add_g.v: -------------------------------------------------------------------------------- 1 | module add_g( 2 | input clk, 3 | input rst, 4 | input [10:0] data_0, 5 | input [10:0] data_1, 6 | output reg signed [11:0] result); 7 | 8 | always @ (posedge clk) 9 | begin 10 | if(rst) 11 | result <= 0; 12 | else 13 | result <= data_1 - data_0; 14 | end 15 | 16 | endmodule -------------------------------------------------------------------------------- /dilate.v: -------------------------------------------------------------------------------- 1 | module dilate( 2 | input clk, 3 | input rst, 4 | input [10:0] hcount, 5 | input [10:0] vcount, 6 | input erode_value, 7 | output [11:0] dilate_value 8 | ); 9 | parameter Hor_Addr_Time = 800; 10 | parameter Width = Hor_Addr_Time >> 1; 11 | parameter Ver_Addr_Time = 600; 12 | parameter Height = Ver_Addr_Time >> 1; 13 | 14 | reg line_buffer_0 [(Width - 1):0]; 15 | reg line_buffer_1 [(Width - 1):0]; 16 | reg line_buffer_2 [(Width - 1):0]; 17 | 18 | wire pixel[8:0]; 19 | 20 | wire [10:0] div_two_hcount, div_two_vcount; 21 | 22 | genvar line_buffer_i; 23 | generate 24 | for(line_buffer_i = Width - 1; ~line_buffer_i; line_buffer_i = line_buffer_i - 1) 25 | begin:Line_0 26 | always @ (posedge clk) 27 | begin 28 | if(~rst && ~vcount[0] && hcount == 0) 29 | begin 30 | line_buffer_0[line_buffer_i] <= line_buffer_1[line_buffer_i]; 31 | line_buffer_1[line_buffer_i] <= line_buffer_2[line_buffer_i]; 32 | end 33 | end 34 | end 35 | endgenerate 36 | 37 | always @ (posedge clk) 38 | begin 39 | if(~rst && ~vcount[0] && ~hcount[0]) 40 | begin 41 | line_buffer_2[div_two_hcount] <= erode_value; 42 | end 43 | end 44 | 45 | assign div_two_hcount = hcount >> 1; 46 | assign div_two_vcount = vcount >> 1; 47 | 48 | assign pixel[0] = (div_two_hcount >= 2 && div_two_vcount >= 2 && div_two_hcount <= Width + 2 && div_two_vcount <= Height + 2) ? line_buffer_0[div_two_hcount - 2] : 0; 49 | assign pixel[1] = (div_two_hcount >= 1 && div_two_vcount >= 2 && div_two_hcount <= Width + 1 && div_two_vcount <= Height + 2) ? line_buffer_0[div_two_hcount - 1] : 0; 50 | assign pixel[2] = (div_two_vcount >= 2 && div_two_hcount <= Width && div_two_vcount <= Height + 2) ? line_buffer_0[div_two_hcount] : 0; 51 | 52 | assign pixel[3] = (div_two_hcount >= 2 && div_two_vcount >= 1 && div_two_hcount <= Width + 2 && div_two_vcount <= Height + 1) ? line_buffer_1[div_two_hcount - 2] : 0; 53 | assign pixel[4] = (div_two_hcount >= 1 && div_two_vcount >= 1 && div_two_hcount <= Width + 1 && div_two_vcount <= Height + 1) ? line_buffer_1[div_two_hcount - 1] : 0; 54 | assign pixel[5] = (div_two_vcount >= 1 && div_two_hcount <= Width && div_two_vcount <= Height + 1) ? line_buffer_1[div_two_hcount] : 0; 55 | 56 | assign pixel[6] = (div_two_hcount >= 2 && div_two_hcount <= Width + 2 && div_two_vcount <= Height) ? line_buffer_2[div_two_hcount - 2] : 0; 57 | assign pixel[7] = (div_two_hcount >= 1 && div_two_hcount <= Width + 1 && div_two_vcount <= Height) ? line_buffer_2[div_two_hcount - 1] : 0; 58 | assign pixel[8] = (div_two_hcount <= Width && div_two_vcount <= Height) ? line_buffer_2[div_two_hcount] : 0; 59 | 60 | wire or_0, or_1, or_2; 61 | wire or_all; 62 | 63 | assign dilate_value = {12{or_all}}; 64 | 65 | Or Or_dut_0( 66 | .clk(clk), 67 | .rst(rst), 68 | .data_0(pixel[0]), 69 | .data_1(pixel[1]), 70 | .data_2(pixel[2]), 71 | .result(or_0) 72 | ); 73 | 74 | Or Or_dut_1( 75 | .clk(clk), 76 | .rst(rst), 77 | .data_0(pixel[3]), 78 | .data_1(pixel[4]), 79 | .data_2(pixel[5]), 80 | .result(or_1) 81 | ); 82 | 83 | Or Or_dut_2( 84 | .clk(clk), 85 | .rst(rst), 86 | .data_0(pixel[6]), 87 | .data_1(pixel[7]), 88 | .data_2(pixel[8]), 89 | .result(or_2) 90 | ); 91 | 92 | Or Or_dut_all( 93 | .clk(clk), 94 | .rst(rst), 95 | .data_0(or_0), 96 | .data_1(or_1), 97 | .data_2(or_2), 98 | .result(or_all)); 99 | 100 | endmodule -------------------------------------------------------------------------------- /dilate_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | module dilate_tb(); 3 | 4 | reg clk = 0; 5 | 6 | reg [10:0] hcount, vcount; 7 | reg erode_value; 8 | wire [11:0] dilate_value; 9 | 10 | integer i; 11 | integer j; 12 | initial 13 | begin 14 | 15 | vcount = 0; 16 | #5; 17 | 18 | for(j = 0; j <= 10; j = j + 1) 19 | begin 20 | hcount = 0; 21 | clk = 1; 22 | erode_value = j[0]; 23 | #1; 24 | clk = 0; 25 | #5; 26 | 27 | for(i = 1; i <= 20; i = i + 1) 28 | begin 29 | clk = ~clk; 30 | hcount = hcount + 1; 31 | erode_value = i[0]; 32 | #1; 33 | clk = ~clk; 34 | #5; 35 | end 36 | 37 | vcount = vcount + 1; 38 | end 39 | end 40 | 41 | dilate dilate_tb( 42 | .clk(clk), 43 | .rst(1'b0), 44 | .hcount(hcount), 45 | .vcount(vcount), 46 | .erode_value(erode_value), 47 | .dilate_value(dilate_value) 48 | ); 49 | 50 | endmodule -------------------------------------------------------------------------------- /erode.v: -------------------------------------------------------------------------------- 1 | module erode( 2 | input clk, 3 | input rst, 4 | input [10:0] hcount, 5 | input [10:0] vcount, 6 | input sobel_value, 7 | output [11:0] erode_value 8 | ); 9 | parameter Hor_Addr_Time = 800; 10 | parameter Width = Hor_Addr_Time >> 1; 11 | parameter Ver_Addr_Time = 600; 12 | parameter Height = Ver_Addr_Time >> 1; 13 | 14 | reg line_buffer_0 [(Width - 1):0]; 15 | reg line_buffer_1 [(Width - 1):0]; 16 | reg line_buffer_2 [(Width - 1):0]; 17 | 18 | wire pixel[8:0]; 19 | 20 | wire [10:0] div_two_hcount, div_two_vcount; 21 | 22 | genvar line_buffer_i; 23 | generate 24 | for(line_buffer_i = Width - 1; ~line_buffer_i; line_buffer_i = line_buffer_i - 1) 25 | begin:Line_0 26 | always @ (posedge clk) 27 | begin 28 | if(~rst && ~vcount[0] && hcount == 0) 29 | begin 30 | line_buffer_0[line_buffer_i] <= line_buffer_1[line_buffer_i]; 31 | line_buffer_1[line_buffer_i] <= line_buffer_2[line_buffer_i]; 32 | end 33 | end 34 | end 35 | endgenerate 36 | 37 | always @ (posedge clk) 38 | begin 39 | if(~rst && ~vcount[0] && ~hcount[0]) 40 | begin 41 | line_buffer_2[div_two_hcount] <= sobel_value; 42 | end 43 | end 44 | 45 | assign div_two_hcount = hcount >> 1; 46 | assign div_two_vcount = vcount >> 1; 47 | 48 | assign pixel[0] = (div_two_hcount >= 2 && div_two_vcount >= 2 && div_two_hcount <= Width + 2 && div_two_vcount <= Height + 2) ? line_buffer_0[div_two_hcount - 2] : 0; 49 | assign pixel[1] = (div_two_hcount >= 1 && div_two_vcount >= 2 && div_two_hcount <= Width + 1 && div_two_vcount <= Height + 2) ? line_buffer_0[div_two_hcount - 1] : 0; 50 | assign pixel[2] = (div_two_vcount >= 2 && div_two_hcount <= Width && div_two_vcount <= Height + 2) ? line_buffer_0[div_two_hcount] : 0; 51 | 52 | assign pixel[3] = (div_two_hcount >= 2 && div_two_vcount >= 1 && div_two_hcount <= Width + 2 && div_two_vcount <= Height + 1) ? line_buffer_1[div_two_hcount - 2] : 0; 53 | assign pixel[4] = (div_two_hcount >= 1 && div_two_vcount >= 1 && div_two_hcount <= Width + 1 && div_two_vcount <= Height + 1) ? line_buffer_1[div_two_hcount - 1] : 0; 54 | assign pixel[5] = (div_two_vcount >= 1 && div_two_hcount <= Width && div_two_vcount <= Height + 1) ? line_buffer_1[div_two_hcount] : 0; 55 | 56 | assign pixel[6] = (div_two_hcount >= 2 && div_two_hcount <= Width + 2 && div_two_vcount <= Height) ? line_buffer_2[div_two_hcount - 2] : 0; 57 | assign pixel[7] = (div_two_hcount >= 1 && div_two_hcount <= Width + 1 && div_two_vcount <= Height) ? line_buffer_2[div_two_hcount - 1] : 0; 58 | assign pixel[8] = (div_two_hcount <= Width && div_two_vcount <= Height) ? line_buffer_2[div_two_hcount] : 0; 59 | 60 | wire and_0, and_1, and_2; 61 | wire and_all; 62 | 63 | assign erode_value = {12{and_all}}; 64 | 65 | And And_dut_0( 66 | .clk(clk), 67 | .rst(rst), 68 | .data_0(pixel[0]), 69 | .data_1(pixel[1]), 70 | .data_2(pixel[2]), 71 | .result(and_0) 72 | ); 73 | 74 | And And_dut_1( 75 | .clk(clk), 76 | .rst(rst), 77 | .data_0(pixel[3]), 78 | .data_1(pixel[4]), 79 | .data_2(pixel[5]), 80 | .result(and_1) 81 | ); 82 | 83 | And And_dut_2( 84 | .clk(clk), 85 | .rst(rst), 86 | .data_0(pixel[6]), 87 | .data_1(pixel[7]), 88 | .data_2(pixel[8]), 89 | .result(and_2) 90 | ); 91 | 92 | And And_dut_all( 93 | .clk(clk), 94 | .rst(rst), 95 | .data_0(and_0), 96 | .data_1(and_1), 97 | .data_2(and_2), 98 | .result(and_all)); 99 | 100 | endmodule -------------------------------------------------------------------------------- /erode_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | module erode_tb(); 3 | 4 | reg clk = 0; 5 | 6 | reg [10:0] hcount, vcount; 7 | reg sobel_value; 8 | wire [11:0] erode_value; 9 | 10 | integer i; 11 | integer j; 12 | initial 13 | begin 14 | 15 | vcount = 0; 16 | #5; 17 | 18 | for(j = 0; j <= 10; j = j + 1) 19 | begin 20 | hcount = 0; 21 | clk = 1; 22 | sobel_value = j[0]; 23 | #1; 24 | clk = 0; 25 | #5; 26 | 27 | for(i = 1; i <= 20; i = i + 1) 28 | begin 29 | clk = ~clk; 30 | hcount = hcount + 1; 31 | sobel_value = i[0]; 32 | #1; 33 | clk = ~clk; 34 | #5; 35 | end 36 | 37 | vcount = vcount + 1; 38 | end 39 | end 40 | 41 | erode erode_tb( 42 | .clk(clk), 43 | .rst(1'b0), 44 | .hcount(hcount), 45 | .vcount(vcount), 46 | .sobel_value(sobel_value), 47 | .erode_value(erode_value) 48 | ); 49 | 50 | endmodule -------------------------------------------------------------------------------- /get_g.v: -------------------------------------------------------------------------------- 1 | module get_g( 2 | input clk, 3 | input rst, 4 | input [7:0] data_0, 5 | input [7:0] data_1, 6 | input [7:0] data_2, 7 | output reg [10:0] result); 8 | 9 | always @ (posedge clk) 10 | begin 11 | if(rst) 12 | result <= 0; 13 | else 14 | result <= data_0 + (data_1 << 1) + data_2; 15 | end 16 | 17 | endmodule -------------------------------------------------------------------------------- /get_length.v: -------------------------------------------------------------------------------- 1 | module get_length( 2 | input clk, 3 | input rst, 4 | input signed [11:0] data_0, 5 | input signed [11:0] data_1, 6 | output reg [12:0] result); 7 | 8 | always @ (posedge clk) 9 | begin 10 | if(rst) 11 | result <= 0; 12 | else 13 | result <= (data_0 >= 0 ? data_0 : -data_0) + (data_1 >= 0 ? data_1 : -data_1); 14 | end 15 | 16 | endmodule -------------------------------------------------------------------------------- /median_filter.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | module median_filter( 3 | input clk, 4 | input rst, 5 | input [10:0] hcount, 6 | input [10:0] vcount, 7 | input [7:0] Y, 8 | output [7:0] pixel_value 9 | ); 10 | parameter Hor_Addr_Time = 800; 11 | parameter Width = Hor_Addr_Time >> 1; 12 | parameter Ver_Addr_Time = 600; 13 | parameter Height = Ver_Addr_Time >> 1; 14 | 15 | reg [7:0] line_buffer_0 [(Width - 1):0]; 16 | reg [7:0] line_buffer_1 [(Width - 1):0]; 17 | reg [7:0] line_buffer_2 [(Width - 1):0]; 18 | 19 | wire [7:0] pixel[8:0]; 20 | wire [7:0] Min[2:0]; 21 | wire [7:0] Middle[2:0]; 22 | wire [7:0] Max[2:0]; 23 | 24 | wire [7:0] minMax; 25 | wire [7:0] maxMin; 26 | wire [7:0] midMid; 27 | 28 | 29 | //wire [7:0] minMax, maxMin, midMid; 30 | wire [7:0] middlest; 31 | 32 | assign pixel_value = (rst ? 8'b0 : middlest); 33 | 34 | wire [10:0] div_two_hcount, div_two_vcount; 35 | 36 | //wire RealClk; 37 | //assign RealClk = (~hcount[0]) ? clk : 0; 38 | 39 | genvar line_buffer_i; 40 | generate 41 | for(line_buffer_i = Width - 1; ~line_buffer_i; line_buffer_i = line_buffer_i - 1) 42 | begin:Line_0 43 | always @ (posedge clk) 44 | begin 45 | if(~rst && ~vcount[0] && hcount == 0) 46 | begin 47 | line_buffer_0[line_buffer_i] <= line_buffer_1[line_buffer_i]; 48 | line_buffer_1[line_buffer_i] <= line_buffer_2[line_buffer_i]; 49 | end 50 | end 51 | end 52 | endgenerate 53 | 54 | always @ (posedge clk) 55 | begin 56 | if(~rst && ~vcount[0] && ~hcount[0]) 57 | begin 58 | line_buffer_2[div_two_hcount] <= Y; 59 | end 60 | end 61 | 62 | assign div_two_hcount = hcount >> 1; 63 | assign div_two_vcount = vcount >> 1; 64 | 65 | assign pixel[0] = (div_two_hcount >= 2 && div_two_vcount >= 2 && div_two_hcount <= Width + 2 && div_two_vcount <= Height + 2) ? line_buffer_0[div_two_hcount - 2] : 0; 66 | assign pixel[1] = (div_two_hcount >= 1 && div_two_vcount >= 2 && div_two_hcount <= Width + 1 && div_two_vcount <= Height + 2) ? line_buffer_0[div_two_hcount - 1] : 0; 67 | assign pixel[2] = (div_two_vcount >= 2 && div_two_hcount <= Width && div_two_vcount <= Height + 2) ? line_buffer_0[div_two_hcount] : 0; 68 | 69 | assign pixel[3] = (div_two_hcount >= 2 && div_two_vcount >= 1 && div_two_hcount <= Width + 2 && div_two_vcount <= Height + 1) ? line_buffer_1[div_two_hcount - 2] : 0; 70 | assign pixel[4] = (div_two_hcount >= 1 && div_two_vcount >= 1 && div_two_hcount <= Width + 1 && div_two_vcount <= Height + 1) ? line_buffer_1[div_two_hcount - 1] : 0; 71 | assign pixel[5] = (div_two_vcount >= 1 && div_two_hcount <= Width && div_two_vcount <= Height + 1) ? line_buffer_1[div_two_hcount] : 0; 72 | 73 | assign pixel[6] = (div_two_hcount >= 2 && div_two_hcount <= Width + 2 && div_two_vcount <= Height) ? line_buffer_2[div_two_hcount - 2] : 0; 74 | //assign pixel[6] = (div_two_hcount >= 2) ? line_buffer_2[div_two_hcount - 2] : 0; 75 | assign pixel[7] = (div_two_hcount >= 1 && div_two_hcount <= Width + 1 && div_two_vcount <= Height) ? line_buffer_2[div_two_hcount - 1] : 0; 76 | assign pixel[8] = (div_two_hcount <= Width && div_two_vcount <= Height) ? line_buffer_2[div_two_hcount] : 0; 77 | 78 | Compare cmp_dut0( 79 | .clk(clk), 80 | .rst(rst), 81 | .data_1(pixel[0]), 82 | .data_2(pixel[1]), 83 | .data_3(pixel[2]), 84 | .data_min(Min[0]), 85 | .data_middle(Middle[0]), 86 | .data_max(Max[0])); 87 | 88 | Compare cmp_dut1( 89 | .clk(clk), 90 | .rst(rst), 91 | .data_1(pixel[3]), 92 | .data_2(pixel[4]), 93 | .data_3(pixel[5]), 94 | .data_min(Min[1]), 95 | .data_middle(Middle[1]), 96 | .data_max(Max[1])); 97 | 98 | Compare cmp_dut2( 99 | .clk(clk), 100 | .rst(rst), 101 | .data_1(pixel[6]), 102 | .data_2(pixel[7]), 103 | .data_3(pixel[8]), 104 | .data_min(Min[2]), 105 | .data_middle(Middle[2]), 106 | .data_max(Max[2])); 107 | 108 | Compare cmp_maxMin( 109 | .clk(clk), 110 | .rst(rst), 111 | .data_1(Min[0]), 112 | .data_2(Min[1]), 113 | .data_3(Min[2]), 114 | .data_max(maxMin)); 115 | 116 | Compare cmp_midMid( 117 | .clk(clk), 118 | .rst(rst), 119 | .data_1(Middle[0]), 120 | .data_2(Middle[1]), 121 | .data_3(Middle[2]), 122 | .data_middle(midMid)); 123 | 124 | Compare cmp_minMax( 125 | .clk(clk), 126 | .rst(rst), 127 | .data_1(Max[0]), 128 | .data_2(Max[1]), 129 | .data_3(Max[2]), 130 | .data_min(minMax)); 131 | 132 | Compare cmp_Middle( 133 | .clk(clk), 134 | .rst(rst), 135 | .data_1(minMax), 136 | .data_2(midMid), 137 | .data_3(maxMin), 138 | .data_middle(middlest)); 139 | 140 | endmodule -------------------------------------------------------------------------------- /median_filter_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | module median_filter_tb(); 3 | 4 | reg clk = 0; 5 | 6 | reg [10:0] hcount, vcount; 7 | reg [7:0] Y; 8 | wire [7:0] pixel_value; 9 | 10 | integer i; 11 | integer j; 12 | initial 13 | begin 14 | 15 | vcount = 0; 16 | #5; 17 | 18 | for(j = 0; j <= 10; j = j + 1) 19 | begin 20 | hcount = 0; 21 | clk = 1; 22 | Y = vcount; 23 | #1; 24 | clk = 0; 25 | #5; 26 | 27 | for(i = 1; i <= 20; i = i + 1) 28 | begin 29 | clk = ~clk; 30 | hcount = hcount + 1; 31 | Y = i[7:0] + vcount; 32 | #1; 33 | clk = ~clk; 34 | #5; 35 | end 36 | 37 | vcount = vcount + 1; 38 | end 39 | end 40 | 41 | median_filter filter( 42 | .clk(clk), 43 | .rst(1'b0), 44 | .hcount(hcount), 45 | .vcount(vcount), 46 | .Y(Y), 47 | .pixel_value(pixel_value) 48 | ); 49 | 50 | endmodule -------------------------------------------------------------------------------- /sobel_detect.v: -------------------------------------------------------------------------------- 1 | module sobel_detect( 2 | input clk, 3 | input rst, 4 | input [10:0] hcount, 5 | input [10:0] vcount, 6 | input [7:0] median_value, 7 | output [11:0] sobel_value 8 | ); 9 | parameter Hor_Addr_Time = 800; 10 | parameter Width = Hor_Addr_Time >> 1; 11 | parameter Ver_Addr_Time = 600; 12 | parameter Height = Ver_Addr_Time >> 1; 13 | 14 | reg [7:0] line_buffer_0 [(Width - 1):0]; 15 | reg [7:0] line_buffer_1 [(Width - 1):0]; 16 | reg [7:0] line_buffer_2 [(Width - 1):0]; 17 | 18 | wire [7:0] pixel[8:0]; 19 | 20 | wire [10:0] div_two_hcount, div_two_vcount; 21 | 22 | genvar line_buffer_i; 23 | generate 24 | for(line_buffer_i = Width - 1; ~line_buffer_i; line_buffer_i = line_buffer_i - 1) 25 | begin:Line_0 26 | always @ (posedge clk) 27 | begin 28 | if(~rst && ~vcount[0] && hcount == 0) 29 | begin 30 | line_buffer_0[line_buffer_i] <= line_buffer_1[line_buffer_i]; 31 | line_buffer_1[line_buffer_i] <= line_buffer_2[line_buffer_i]; 32 | end 33 | end 34 | end 35 | endgenerate 36 | 37 | always @ (posedge clk) 38 | begin 39 | if(~rst && ~vcount[0] && ~hcount[0]) 40 | begin 41 | line_buffer_2[div_two_hcount] <= median_value; 42 | end 43 | end 44 | 45 | assign div_two_hcount = hcount >> 1; 46 | assign div_two_vcount = vcount >> 1; 47 | 48 | assign pixel[0] = (div_two_hcount >= 2 && div_two_vcount >= 2 && div_two_hcount <= Width + 2 && div_two_vcount <= Height + 2) ? line_buffer_0[div_two_hcount - 2] : 0; 49 | assign pixel[1] = (div_two_hcount >= 1 && div_two_vcount >= 2 && div_two_hcount <= Width + 1 && div_two_vcount <= Height + 2) ? line_buffer_0[div_two_hcount - 1] : 0; 50 | assign pixel[2] = (div_two_vcount >= 2 && div_two_hcount <= Width && div_two_vcount <= Height + 2) ? line_buffer_0[div_two_hcount] : 0; 51 | 52 | assign pixel[3] = (div_two_hcount >= 2 && div_two_vcount >= 1 && div_two_hcount <= Width + 2 && div_two_vcount <= Height + 1) ? line_buffer_1[div_two_hcount - 2] : 0; 53 | assign pixel[4] = (div_two_hcount >= 1 && div_two_vcount >= 1 && div_two_hcount <= Width + 1 && div_two_vcount <= Height + 1) ? line_buffer_1[div_two_hcount - 1] : 0; 54 | assign pixel[5] = (div_two_vcount >= 1 && div_two_hcount <= Width && div_two_vcount <= Height + 1) ? line_buffer_1[div_two_hcount] : 0; 55 | 56 | assign pixel[6] = (div_two_hcount >= 2 && div_two_hcount <= Width + 2 && div_two_vcount <= Height) ? line_buffer_2[div_two_hcount - 2] : 0; 57 | assign pixel[7] = (div_two_hcount >= 1 && div_two_hcount <= Width + 1 && div_two_vcount <= Height) ? line_buffer_2[div_two_hcount - 1] : 0; 58 | assign pixel[8] = (div_two_hcount <= Width && div_two_vcount <= Height) ? line_buffer_2[div_two_hcount] : 0; 59 | 60 | wire [10:0] gx_0, gx_2; 61 | wire [10:0] gy_0, gy_2; 62 | 63 | get_g get_g_dut_gx_0( 64 | .clk(clk), 65 | .rst(rst), 66 | .data_0(pixel[0]), 67 | .data_1(pixel[3]), 68 | .data_2(pixel[6]), 69 | .result(gx_0)); 70 | 71 | get_g get_g_dut_gx_2( 72 | .clk(clk), 73 | .rst(rst), 74 | .data_0(pixel[2]), 75 | .data_1(pixel[5]), 76 | .data_2(pixel[8]), 77 | .result(gx_2)); 78 | 79 | get_g get_g_dut_gy_0( 80 | .clk(clk), 81 | .rst(rst), 82 | .data_0(pixel[0]), 83 | .data_1(pixel[1]), 84 | .data_2(pixel[2]), 85 | .result(gy_0)); 86 | 87 | get_g get_g_dut_gy_2( 88 | .clk(clk), 89 | .rst(rst), 90 | .data_0(pixel[6]), 91 | .data_1(pixel[7]), 92 | .data_2(pixel[8]), 93 | .result(gy_2)); 94 | 95 | wire signed [11:0] gx, gy; 96 | 97 | add_g add_dut_gx( 98 | .clk(clk), 99 | .rst(rst), 100 | .data_0(gx_0), 101 | .data_1(gx_2), 102 | .result(gx)); 103 | 104 | add_g add_dut_gy( 105 | .clk(clk), 106 | .rst(rst), 107 | .data_0(gy_2), 108 | .data_1(gy_0), 109 | .result(gy)); 110 | 111 | wire [12:0] length; 112 | 113 | get_length get_length_dut( 114 | .clk(clk), 115 | .rst(rst), 116 | .data_0(gx), 117 | .data_1(gy), 118 | .result(length)); 119 | 120 | threshold_detect threshold_detect_dut( 121 | .clk(clk), 122 | .rst(rst), 123 | .length(length), 124 | .result(sobel_value)); 125 | 126 | endmodule -------------------------------------------------------------------------------- /sobel_detect_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | module sobel_detect_tb(); 3 | 4 | reg clk = 0; 5 | 6 | reg [10:0] hcount, vcount; 7 | reg [7:0] median_value; 8 | wire [11:0] sobel_value; 9 | 10 | integer i; 11 | integer j; 12 | initial 13 | begin 14 | 15 | vcount = 0; 16 | #5; 17 | 18 | for(j = 0; j <= 10; j = j + 1) 19 | begin 20 | hcount = 0; 21 | clk = 1; 22 | median_value = vcount; 23 | #1; 24 | clk = 0; 25 | #5; 26 | 27 | for(i = 1; i <= 20; i = i + 1) 28 | begin 29 | clk = ~clk; 30 | hcount = hcount + 1; 31 | median_value = i[7:0] + vcount; 32 | #1; 33 | clk = ~clk; 34 | #5; 35 | end 36 | 37 | vcount = vcount + 1; 38 | end 39 | end 40 | 41 | sobel_detect sobel_detect_dut( 42 | .clk(clk), 43 | .rst(1'b0), 44 | .hcount(hcount), 45 | .vcount(vcount), 46 | .median_value(median_value), 47 | .sobel_value(sobel_value) 48 | ); 49 | 50 | endmodule -------------------------------------------------------------------------------- /threshold_detect.v: -------------------------------------------------------------------------------- 1 | module threshold_detect( 2 | input clk, 3 | input rst, 4 | input [12:0] length, 5 | output reg [11:0] result); 6 | 7 | parameter threshold = 140; 8 | 9 | always @ (posedge clk) 10 | begin 11 | if(rst) 12 | result <= 0; 13 | else 14 | result <= (length >= threshold ? {12{1'b1}} : 0); 15 | end 16 | 17 | endmodule --------------------------------------------------------------------------------