├── 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
--------------------------------------------------------------------------------