找回密码
 注册
关于网站域名变更的通知
查看: 257|回复: 1
打印 上一主题 下一主题

简单sobel图像边缘检测加速器的设计,实现,仿真与综合

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-5-28 11:02 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
  d7 Q+ U. k5 z
引言, M6 r- K( h; z. k/ y
图像视频处理等多媒体领域是FPGA应用的最主要的方面之一,边缘检测是图像处理和计算机视觉中的基本问题,所以也是最常用的,随着数据量的不断增加以及对实时性的要求,一般软件已经不能满足实际需要,这时,就需要专门的硬件来实现加速。本小节就实现一个简单的sobel边缘检测加速器,为了便于对比,我们还编写对应的软件算法。0 ~! T. ]- j2 ]) ?! C7 F3 L
3 b  l: J& J# \, F9 f+ q
9 |9 j) d6 A. Z- `$ t/ ~# Y  `$ R

5 Y8 M2 Q2 b3 `, ]1,基本思想与算法
( ~" d3 Q) @- y3 TSobel检测法通过一个叫做卷积的过程来估计每个像素点每个方向上的导数值。把中心像素点和离它最近的八个像素点每个乘以一个系数后相加。该系数通常用一个 的卷积表(convolution mask)来表示。分别用于计算x和y方向导数值的Sobel卷积表 Gx和 Gy 如下图所示。# O3 m. S8 K: |" O- z* A
! @. ^2 f* r  B2 u8 k* ]) o
Gx: ! B7 s% G3 s: N9 ^% g& w
" u! V( \; q5 O! x1 U. A. k
Gy:
' Z& ]/ ~) j6 n% b9 ?4 @
3 a1 t# x; h; ~0 l$ N: ?
! S% ~8 D6 t& u4 n5 k我们把每个像素值分别乘以卷积表中对应的系数,再把相乘得到的九个数相加就得到了x方向和y方向的偏导数值 Dx和 Dy。然后,利用这两个偏导数值计算中心像素$ h  o/ o2 F8 d1 |
点的导数。计算公式如下:0 u& O4 A4 j  o2 r6 g: W, E

* W9 x. ?' Z" ^( X9 M, p
! _2 ?( B$ Y6 w+ Z9 g( I. T; w- J' _: u( r) D
由于我们只想找到导数幅值的最大值和最小值,对上式作如下简化:
0 M; a0 H- _: N  L( C5 @% h$ k, J# e, n$ M. {

& q0 s, E4 [1 Y% }/ _' e
, R! O' p) @, P7 y这样近似能够满足计算要求,因为开平方和平方函数都是单调的,实际计算幅度的最大值、最小值与近似以后计算的最大值、最小值发生在图像的同一个地方。并且,与计算平方和开平方相比,计算绝对值所用的硬件资源少得多。
( e, a  h4 m! C# d- Q3 P1 l; t; C2 w4 @, z) B. }( a7 X% R. |7 p
我们需要重复地计算图像中每个像素位置的导数幅值。但是,注意到环绕图像边缘的像素点并没有一个完整的相邻像素组来计算偏导数和导数,所以我们需要对这些像素进行单独处理。最简单的方法就是把图像中边缘像素点的导数值值 |D|设置为0。这可以通过软件来完成。
5 U6 B- `8 P9 c; A( v8 D8 l* O, i  R4 v5 ?) I1 K
我们用伪代码来表示该算法。令O[row][col] 表示原始图像的像素点,D[row][col]表示导数图像的像素点,row的范围从0到hight,col的范围从0到width。同时令Gx[j] 和 Gy[j] 表示卷积表,其中i 和 j 的范围从 -1 到 1.   Y% o# R8 w5 X, V
6 [) J0 m% K: O$ [1 `, G* Y. I* ]* e
/ _9 a1 I( s( B7 k$ U

- S, X( f0 u% C2 g1 I6 _for( row=1; row<=hight; row=row+1 )
' u2 p) G; M' R0 V2 n  M% y% w5 J {
/ K) c7 M' j, A       for(col=1; col<=width; col=col+1)" b5 `/ u* V! n
        {! H- P  g# Y$ O" W9 j! J
                  sumx=0;        sumy=0;
+ x& R! |) `8 T" F- _9 |* W/ M                for( i = -1; i <= +1; i = i+1)   
% y; f+ n7 R: D2 I                {                                % B: c! y- o& n6 u8 N
                        for (j = -1; j<= +1; j = j+1)  % b+ G2 v8 \! W2 Z0 W
                        {                        8 i& [# [2 V9 I
                                sumx = sumx + O[row+i][col+j] * Gx[j];
. D$ K* q! T7 H, w3 @, d3 p8 M                                sumy = sumy + O[row+i][col+j] * Gx[j];% V# w3 I9 P9 g. t$ |0 m
                         }
* ?7 V7 ~' C+ F( l                     }
, k& e( i9 ~  ?8 i6 G) f# d% T                        D[row][col] = abs(sumx) + abs(sumy)' W) E: G- p+ J+ z
        }6 f+ d& e* w$ q( P0 E" b
}' K: Z4 b- ?( I' Z5 l- N

  S- Q2 [) H* U2 A$ w
, f/ T3 T0 E" d- B' ^, q- R2 ~
4 k& D5 v3 M: \) N! `
% ~9 ^/ c+ h; G7 L5 G& f" u; B+ l
/ D0 H, U  [  E8 T/ I6 c3 U$ G8 o8 h% K* [4 j: M
2,硬件实现
' c+ t! V/ L  p  Q0 ]. C3 [一旦明白了sobel的实现算法,我们就可以根据算法来划分模块了,本例中将sobel分成了:addr_gen,compute,machine,sobel_salve四个不同的子模块和sobel一个顶层模块。
8 q& S& r% W8 A5 T
2 e7 p7 O' k- ]" n) r3 I需要说明的是,sobel加速器最终要挂载SoC的总线上,所以需要一个统一的接口总线,本例中采用wishbone总线,关于wishbone总线的内容,请参考:http://blog.csdn.net/rill_zhen/article/details/86597887 A$ E' r/ W% c; z" O

$ Y1 t$ F6 I6 g" T) }. R; z. {此外,由于sobel加速器只加速核心的数据处理部分,但是,对于一张完整的图片(例如bmp)还有其文件头,所以bmp的文件头的数据需要事先去掉,当sobel处理完后也需要再加上文件头之后才能用图片阅读器打开。所以我们需要编写相应的软件程序。
- a. Y/ Q2 N4 ]6 B  E) j- q1 g+ B/ g# l
下面只给出verilog代码清单:
1 k+ b+ H" }  n/ A! r; F. A! z) ~1 B# h% X) ^& j8 J6 a" u5 z$ b
. h5 S8 i. }9 a7 |  l) J2 f
) t6 }1 Z7 G9 S& v! r- r
sobel.v
9 _9 w- j& _5 k3 ]! M) O4 Z" f  N
) s/ U, x) I1 v. ?) {2 D: W
, ]$ G  F" I1 H2 k+ G
`timescale 10ns/10ns0 H. i: O; b0 m; C' k. K5 R9 i
module  sobel    (9 Q! U  a3 h# |" E6 @
                 //master slave share i/f
1 T1 m/ R9 T( c" d, O                 clk_i,
; x* q, n& @% M( v: h                 rst_i,6 u, ?' M  I# h8 |1 A
                 dat_i,
' b7 S8 V! z$ n5 U' t  |                 dat_o,
- Z1 F2 S8 h2 G) l' J                 //master i/f9 L6 T8 k# ^3 Y4 B
                 cyc_o,
% M; o  v5 n+ G3 _                 stb_o,: @! ^$ }! C$ j
                 we_o,
! k  [/ U) o1 u$ g4 }3 K                 adr_o,9 t1 t2 d( M# i; H
                 ack_i,8 o+ K1 Z9 a- W
                 //slave i/f
0 i. f1 A5 r& f& V0 i& o' ]/ n                 cyc_i,
: G' Y) g+ ~8 u6 G( w$ [                 stb_i,. R' H9 X/ x0 n( N! r, X
                 we_i,6 w. N+ O$ R( D9 c; R( G2 Z
                 adr_i,
) `3 F# Y; u% w3 N0 M                 ack_o,$ x/ _9 n% _+ @4 b
                 //debug i/f5 V' Y5 K! d4 Y) [
                 prev_row_load,
, m, L! S* c- o9 u: w                 curr_row_load,
! F1 s' s3 Y4 c' p: J7 ~                 next_row_load,* V% c9 X3 i# D3 P9 c+ _
                 current_state,6 I% [! i: G: W4 Q
                 int_req//interrupt
0 t0 i/ Y) b5 q# \. ~) q2 u                 );
: D/ T" D0 Y6 J- n                 
' a" r9 R. w5 I9 u# b* }8 kinput  clk_i;
" m# g- M7 v5 m4 [input  rst_i;
! O" V$ M* b1 F6 {, N6 oinput[31:0]   dat_i;
; ]3 z$ I$ v& ^% N6 V+ H$ koutput[31:0]  dat_o;
; E2 C# ]6 W# p+ zoutput   cyc_o;
1 f" K- `, }4 Goutput   stb_o;
$ P% K4 _6 @: G  Noutput   we_o;9 o# Z1 J. B0 D( A! K6 h
output[21:0]   adr_o;
$ N1 V$ S+ _7 Xinput    ack_i;2 S; i6 O1 G+ d: e* \2 l# y
input    cyc_i;
, I: y- ^7 x7 qinput    stb_i;
. ~; n% }7 q8 K3 }. ]input    we_i;
; h; s) D: _# m0 winput[21:0]    adr_i;1 Z/ C  O' c& J) u6 b
output   ack_o;
; Z" p' a' B% E+ i$ a# Doutput   prev_row_load;
3 b) n4 }6 c0 voutput   curr_row_load;2 |1 p: F- I/ `0 l4 N7 H% \$ U' j3 p
output   next_row_load;* ]; x5 x2 P0 s& g' G
output[4:0]   current_state;" M9 y+ j0 \3 |2 l8 ~7 K: @: `# a
output   int_req;
3 a* k: x3 n' ]* O9 r+ y * ~2 W' p( ~' E
wire   start;
/ Q" F( i0 S! Z3 s7 Bwire   ack_i;
6 }+ O9 k6 w- G7 ?wire   cyc_o;. E8 ]6 V5 \( Q3 w
wire   stb_o;
0 G& c8 a/ S- [8 `, qwire   we_o;
  F* O7 K1 M9 v( w# g9 xwire   O_base_ce;! S- R1 @3 N2 S
wire   D_base_ce;4 b% K- R7 u7 f! M" g2 _; \! A, g
wire   done_set;4 P9 p' b" a/ n; B9 p. O
wire   shift_en;; J. j; H! N5 x7 X- ^
wire   prev_row_load;
7 d1 z$ Q3 E+ g, m) {) Wwire   curr_row_load;
3 ?$ P1 T/ Y- \5 V5 Iwire   next_row_load;
+ X6 y+ H7 \7 y$ @0 A) D) {# F7 ewire   O_offset_cnt_en;5 `5 c& n+ E/ ^) ?- ]) ^4 I
wire   D_offset_cnt_en;: C( n) T. N- _0 g# ?. H
wire   offset_reset;
, B% x' \; u9 kwire[31:0]   result_row;, Q: [- b3 Q; |% w
wire[31:0]   dat_i;6 e9 A* k2 i2 Z
wire[21:0]   adr_o;
( `9 F' Z6 l+ `1 w1 k8 G& ewire ack_o;
0 v% v) o  [" Z. Z# @wire[31:0]  dat_o ;               
" `) D. c- T7 x0 q- F
# d% h: n! y% t1 r( ~7 [wire[4:0]  current_state;
- S* S1 ], ?7 N# p
* I: l9 Q6 j1 D5 l! d3 Y7 ^//module sentence8 V1 C* M. D1 j: _& T
) l( P4 J* _: {! J
compute compute(. H+ V8 |1 J4 D- _( l. b% V
                .rst_i(rst_i),
% ^. _# }, y, [. [0 E! f0 l9 I                .clk_i(clk_i),
0 \5 f4 x9 s( {# G/ Z4 n( m                .dat_i(dat_i),2 g9 V' @$ H  {( G7 [' N6 F8 ~
                .shift_en(shift_en),5 h$ E" R4 Y* v/ U3 T$ r
                .prev_row_load(prev_row_load),
2 u- V. _, |+ E) `' b# j                .curr_row_load(curr_row_load),. _7 C8 b, m# j) g6 n
                .next_row_load(next_row_load),
* s- P. `: X3 G0 o: H                .result_row(result_row)% ]9 W! p2 t2 c3 E& U+ T4 s, J
                );3 F# |" n3 h5 }  x0 s/ B7 L3 }6 |' u0 g
. z# A& M) U- k: k  h- M6 V2 N. P
addr_gen addr_gen(
6 b% M- P6 Y) S1 m, y% j                .clk_i(clk_i),
5 t9 d) o4 b' ^7 ?                .dat_i(dat_i),) S* U; w, g/ j$ y
                .O_base_ce(O_base_ce),
" d  S  e  h& D0 E4 H8 i                .D_base_ce(D_base_ce),
( w, D) k6 ~5 F, w( j. _# q0 J                .O_offset_cnt_en(O_offset_cnt_en),
+ e4 r/ `  z& H( y0 l                .D_offset_cnt_en(D_offset_cnt_en),$ s1 w9 a" r+ O
                .offset_reset(offset_reset),
3 ^- ^" i) j' r( w+ _9 H                .prev_row_load(prev_row_load),
: \) F( h8 z$ N$ p- _9 J- S3 D# O                .curr_row_load(curr_row_load),4 p' j' K( {8 K! K- [7 H
                .next_row_load(next_row_load),: ?3 Y- f, f$ h! `3 D: R' [8 K
                .adr_o(adr_o)3 P' A$ F% V6 ^" t  [' ]5 F
                );
$ ]) l2 m+ z& c, g+ y9 s+ x+ Wmachine machine(3 G% i' y8 r5 \; v
               .clk_i(clk_i),
6 A& i1 L7 |4 r/ u8 ~               .rst_i(rst_i),1 g: ^! G0 C5 Q. V
               .ack_i(ack_i),, r* E6 X' P9 a% z# u! @% ^
               .start(start),
+ Z* [" l: g2 [0 [" y) t  k               .offset_reset(offset_reset),
/ D# v) \$ C, b. E; ?# `9 ?               .O_offset_cnt_en(O_offset_cnt_en),3 q7 A5 h7 t0 Y. c8 R: f6 p/ b0 f
               .D_offset_cnt_en(D_offset_cnt_en),
( [; f( _: D4 {4 [% h7 y               .prev_row_load(prev_row_load),
3 x# k& d4 F  _* h               .curr_row_load(curr_row_load),6 K8 Z+ n7 c$ k: \# @
               .next_row_load(next_row_load),
; r. T# T, r' b               .shift_en(shift_en),9 I5 c6 T8 y" F3 T3 K8 R" \# v
               .cyc_o(cyc_o),
! Y: c4 a9 A, h: n( s- q" I/ Z               .we_o(we_o),9 d2 W& r% }1 ?" k  \) Z( `
               .stb_o(stb_o),
, V5 a+ H+ U; w* C$ t+ `               .current_state(current_state),
! e% c* o7 y8 E5 n3 U               .done_set(done_set)
1 i. g. K1 Z( H5 \               );
  r4 b5 G; D) {" w  Ksobel_slave sobel_slave() _; V7 [) p' R( E; Y/ X7 k
                 .clk_i(clk_i),4 E6 L/ R0 g1 K5 _& ^
                 .rst_i(rst_i),
4 P1 P" I8 D7 c                 .dat_i(dat_i),
! h$ q6 {- D- @. A) I                 .dat_o(dat_o),                 
. ]( Y: C  l; g( c! ]1 S                 .cyc_i(cyc_i),
. t; U1 |/ [) I0 d- B9 X- N                 .stb_i(stb_i),& f! S# d+ \' L* t' o# j5 j! r
                 .we_i(we_i),
( j5 O# _9 p6 ]3 g$ Z) {                 .adr_i(adr_i),
; P; J; N, k4 g* r+ T1 @2 ~/ [                 .ack_o(ack_o),
: i9 U6 G# K7 N3 _+ Y! `8 n                 .start(start),  m% E0 w6 f2 n1 ~
                 .O_base_ce(O_base_ce),4 }: O4 p+ |3 Q) |4 `
                 .D_base_ce(D_base_ce),8 {) t) J& H  `- f8 Z$ n
                 .int_req(int_req),
" u+ l$ Z4 O. g/ a$ d$ f                 .done_set(done_set),5 ?7 o/ a8 Y9 s/ G
                 .result_row(result_row)
; `  F: a6 }7 n6 ]$ s                 );               
6 _, \" R$ a, |8 j$ N0 L& @5 Z4 iendmodule
: M8 M) f' k3 S2 P/ Q  b7 p' f7 }% P
addr_gen.v
! a+ ]+ j! Y8 \1 ~) `) X9 u7 ]5 @+ x
* J1 d5 c- c' v/ l5 V' }
`timescale 10ns/10ns6 F1 C( n, ^6 e+ ]+ ^, A: a5 M0 H( n
module addr_gen(
% \! z4 w' E$ c8 b9 }8 d' f                //input
, H3 D; y! U( T" y2 Z; x                clk_i,
5 _0 h( U, n% z/ N3 J8 j) q+ ?. n                dat_i,
3 [& o5 l& g) F                O_base_ce,
8 o* L% g/ K0 I                D_base_ce,
8 \$ U. A- Z7 O5 w) I                O_offset_cnt_en,
9 w7 z5 j4 t' t$ z                D_offset_cnt_en,* D- {( \$ f2 |" O
                offset_reset,
& b* {- H* Q. E0 h! |" n/ \                prev_row_load,! _# h- `3 j5 w2 W/ t) ~
                curr_row_load,
) s' V, g9 e. F9 M0 Q0 s4 V. `. F! s                next_row_load,7 b' z+ v1 R% E% ~' ^' v" ^
                //output: _+ N$ f9 d+ ]2 c4 \# w$ g
                adr_o
$ e' {+ `1 p% v5 z$ ~7 C# H                );
: d6 w8 r) H, L                                
; O# f9 P+ k+ I! \input clk_i;
  @1 O) O8 B! Xinput[31:0]   dat_i;
7 o- l, F/ h$ z# o% A1 s) Zinput   O_base_ce;# L" S& d, g$ T1 K+ s3 J/ T* Q
input   D_base_ce;6 p5 R/ |+ J7 ^% o( E
input   O_offset_cnt_en;
8 ?* x1 q3 _% k- finput   D_offset_cnt_en;              ' h: O' Y6 ]) I3 K2 V  n$ k$ {% d
input   offset_reset ; 2 I# Z3 T* `4 k) q* v
input   prev_row_load;        
% H( e3 ^8 _% d+ A7 C$ H; o1 ginput   curr_row_load;      
  i+ f" C0 G4 Einput   next_row_load;
# J2 H+ @8 ]* K2 L( N ( @5 I& L* j! h  {
output[21:0]  adr_o ;      
6 A/ N" S5 \" f8 f9 D 3 y9 ]0 W6 M& j. a4 r
parameter WIDTH = 1024;) J8 D  C- s, r! a; X

  E/ c4 O* e& i9 R4 [# H  C6 ?; ?: Q3 Rreg[19:0]  O_base ;
. t8 a8 k* Z: t1 _' ?reg[19:0]  D_base ;               6 w$ ?& s, }4 k
reg[18:0]  O_offset;$ Q) v/ t! {# d, ~$ K/ x" H' c$ l; j6 G4 i
reg[18:0]  D_offset;- I- A" S' _+ Q3 [' s$ ~. y' O
wire[19:0]  O_prev_addr;( x! k5 a: L4 ^1 p: A/ \0 b7 d
wire[19:0]  O_curr_addr;
+ @" G$ Y+ m' `- cwire[19:0]  O_next_addr;         ; e6 E* t6 A/ z# L# H
wire[19:0]  D_addr; ! j' M) w9 b2 h9 _6 s+ d" l. {

0 a/ _+ f1 V+ S8 Y8 |+ p( ?/*******************************************************// P4 h+ B& }7 K4 ~, {
. m* ~8 B3 _- m- q$ F9 d2 W
always        @(posedge        clk_i) //original data offset
+ k/ v9 h. [; M$ B" l        if(O_base_ce)        $ F! P  X7 J4 H8 a3 z% q
          O_base        <= dat_i[21:2];* S8 n7 Z+ G; v8 i
always        @(posedge        clk_i)        //original data offset cnt# U6 [2 v  _4 P5 L6 q6 ]. B' x
        if(offset_reset)               
  u' @2 M  P5 {7 G# W7 n/ L6 e" p                O_offset        <= 0;
$ X5 d/ v% d& M: L9 Y9 A        else        
2 A  s  g( A/ R; H+ l+ L          if(O_offset_cnt_en)        0 ^3 k" L% p& A& d2 A% o  w. b
                  O_offset        <= O_offset+1;
) m, h% v8 M4 n: a3 d. E7 l" ]               
. T& A1 X" m" k/*******************************************************/7 D' H3 Q+ ^) Y% y
assign         O_prev_addr = O_base + O_offset;/ P$ ?7 Y! }1 }8 ?- M
assign         O_curr_addr = O_prev_addr + WIDTH/4;; m3 W. N! y/ b" v
assign         O_next_addr = O_prev_addr + 2*WIDTH/4;
# V% |5 V  d% T4 g% h, ?+ F/*******************************************************/& \) f. T* ^9 D" v7 H7 _
always        @(posedge        clk_i)        //destination data offset# c, F( ?' |4 R1 y
        if(D_base_ce)  {% |3 j' Q% |& f5 Z
                D_base        <=dat_i[21:2];9 j, |* y$ v' G+ s5 V6 Z( ?5 C
always        @(posedge        clk_i)        //destination data offset cnt4 j2 H4 j3 M8 `0 D" W
        if(offset_reset)               
! w$ ?: n" ^8 ]6 N: T7 w. D                D_offset        <= 0;) d+ X+ P/ ]  A8 O$ ?
        else        
2 `- N( h) }0 I& u# y& W  I          if(D_offset_cnt_en)        5 q& I) R, A8 k- ~8 P6 m  b
             D_offset        <= D_offset+1;
6 k: K/ y& t+ l6 u1 f                 1 ]* F7 R$ c9 ?
/*******************************************************/) g4 ?0 \" R, x, c
assign D_addr = D_base +D_offset;) M  @! V! h3 Z  j
/*******************************************************/# s1 W  h8 X# a. u/ x
assign        adr_o[21:2] =    prev_row_load ? O_prev_addr :: K7 d4 z! {1 y' |2 v
                                                 curr_row_load ? O_curr_addr :
: M+ s& ~8 V0 R7 {! Y                                                 next_row_load ? O_next_addr :( W8 ~6 ^: X: O$ O. {! K0 o
                                                 D_addr;
( d' B$ p* @: M. W) |                                                 % X2 o( l, U+ `% u
assign adr_o[1:0]        =        2'b00;5 ?" c; q; b9 [8 f1 D. i
endmodule7 o: y# x8 Q1 [6 B8 O

+ _. [$ A+ O: ^# s3 B* K( [  q6 M6 g% v: E
compute.v
! s+ [' L8 J: `$ Z% ~! U" d
( [% ^# I& t& F8 Q7 a) U
$ K  h( G1 m' n
, \; l: z! _  ]/ ^; A# ``timescale 1000ns/10ns
- R" [. b6 {8 S( ]7 R' @; ~0 [  u   {) K3 _4 {5 P+ I
module compute(
( p& F5 z+ {7 z. f; C               //input7 y) x! A3 f# u' n7 I# b2 ]
               clk_i,
- z( a# \7 @7 l. s5 Q: ]1 _$ B               dat_i,. z5 O5 X) J, J; ]
                           rst_i,2 b" x8 O* ^# L( i4 g
               shift_en,
4 X, v6 k: G2 D1 N! A) s               prev_row_load,8 X/ Q( X# V0 j! F+ {' ]# w) ?
               curr_row_load,7 r& A- e  Y5 n/ `8 ]- w' [
               next_row_load,4 T( M( _. A+ }  K, G1 z! o
               //output& E: m: L( `- K9 o6 U
               result_row" C- M* j2 _. j
               );  Q/ y1 X, R( M, Y- U

, V' u3 `8 J6 f! ~1 z# kinput clk_i;5 u4 G0 b0 x9 V+ @
input rst_i;
+ s6 }% T1 s; n0 J! ?input[31:0]   dat_i;
! h2 e1 w, q; |) `8 B0 @input  shift_en;
# W7 F6 L& c# u& k# Q+ K- y- t. Yinput  prev_row_load;0 R$ N( ?6 G  {3 _# u3 N
input  curr_row_load;' _( x- Z. _1 V( {& p
input  next_row_load;
3 F2 |' _* c; Q* K  J" p8 }" owire [7:0] D1 ;
+ B% F! D! l! m" woutput[31:0]  result_row  ;   
0 c/ R# Q2 V9 \8 B2 r7 d               * t. s8 N+ S8 ]6 f# U% B
' K/ ?6 ]! r- K( _: h* Z4 u
reg                                [31:0] prev_row=0, curr_row=0, next_row=0;- a* v) |1 ^5 Y1 p8 X
reg                                [7:0]        O[-1:1][-1:1];
8 Q* @6 h. ^: M+ b5 l  \6 }
4 Q) I7 s# o7 y0 T5 lreg signed         [10:0]        Dx=0, Dy=0;
3 [8 {  O6 D* b $ V( u/ g/ Z, L1 K
reg                                [7:0]        abs_D = 0 ;7 k% r1 ^7 D) t* `; {7 O5 |# V$ j
reg                                [31:0]        result_row =0 ;5 ]! @  C) H0 b$ B! l3 G
7 ?( P4 N% L  x# ~, G* V

+ ~5 b# o5 c$ g2 {  halways@(posedge clk_i)) E$ X( M9 v# ~+ O7 U7 C. A
        if(prev_row_load)          ( f% g) Y7 ^8 y) q( j  B' j
           prev_row        <= dat_i;, b1 [2 z) X% u2 s
        else - F$ y1 G3 d5 F8 s+ G! A
          if(shift_en)               
) s; P0 ~. A) i            prev_row[31:8] <= prev_row[23:0];7 w$ D* u# R% c; D) j  A
: a- u, x. c( J; C7 n2 J5 o$ ~
always@(posedge clk_i)1 J2 S. I+ R+ w3 k, U) l1 O$ C' P. @
        if(curr_row_load)         ! ~) J% t4 ]9 F+ t/ h0 Z8 q
           curr_row<= dat_i;
5 v2 o3 o% Q5 l. G9 H        else 2 ]0 }* m; M5 r, m! N  ~7 b' A
          if(shift_en )     Q( a7 W. D8 H; ?' M6 H8 b
            curr_row [31:8]<=curr_row[23:0];
! \# O& p: }; j: B8 A) r6 e
* U( {& h+ G0 C& q3 s9 d! \) galways@(posedge clk_i)' m! c1 m: V  ]0 u6 W
        if(next_row_load)         
5 d  r% b" W5 F: ~5 n           next_row<=dat_i;+ _$ J9 Z0 x  d9 f6 v) y4 l' N
        else2 K7 T2 M  f4 L
          if(shift_en )        
$ ?3 t" X* D- M: a, Y& D# [0 p0 h5 \             next_row [31:8]<=next_row[23:0];/ i" C9 p  L) R. E4 h  P: Z& W2 D, N

, \7 n2 D. c, M. \
  g' h$ [3 a8 sfunction [10:0]        abs ( input signed [10:0] x);
% |% j5 @- e; y* k" U) T" n        abs = x >=0 ? x : -x ;
/ ^! W5 K; U0 |4 Uendfunction
* B# h' n9 i0 b; \/ f
3 @& N9 h; h+ x //comput pipeline* o  @6 Y# g( M. B; G6 ?- h# _/ H

6 w0 i$ ]1 ?; f0 }always @(posedge clk_i) 7 Y  I3 y. b8 b% f
   if(rst_i)
/ c8 O  Y! H4 `5 x( V      begin
& m  L$ J/ v  S( \            O[-1][-1]<=0;4 T5 g* {  U5 V5 N
                  O[-1][ 0]<=0;
7 X1 ~  a  d7 i1 H& u9 u                  O[-1][+1]<=0;
/ i) ^$ q. G; e% R9 e+ l7 X' t$ Q                  O[ 0][-1]<=0;  d( h$ G" |( \+ W% j) w- X" r
                  O[ 0][ 0]<=0;
. ^) e3 ]' h4 t$ f0 s                  O[ 0][+1]<=0;% d# d5 z$ X- V5 D& k: h
                  O[+1][-1]<=0;. T& j0 C2 p" T  i/ }: Z# D: W2 O, e0 b
                  O[+1][ 0]<=0;8 ^: }; B7 J* ], k
                  O[+1][+1]<=0;* ]# g$ A3 r  T7 x: m
           end
! m1 Z- I$ m1 e* Q) \" h/ y9 |* b        else
9 M$ {3 W. i& ~3 C% \. `        if ( shift_en )         5 v  w' T6 {* l! L# K
        begin# z( }( K: b" j8 A0 ]8 p$ }
                abs_D <= (abs(Dx) + abs(Dy))>>3 ;
) W  |3 I) G2 T+ r! G        
* I- I( E* k* ?9 Z4 ?4 U5 p& G                Dx        <= -$signed({3'b000, O[-1][-1]})        //-1* O[-1][-1]4 c. q/ e  F) `% \/ Z! y" e
                                +$signed({3'b000, O[-1][+1]})        //+1* O[-1][+1]
0 m3 O3 E1 e0 Z! E                                -($signed({3'b000, O[ 0][-1]})        //-2* O[ 0][-1]
( r$ w# n5 A* Z  X* j                                                <<1)
. j0 P! s. {9 J. c2 p# B7 N                                                
5 @6 s$ |- @' x" ~1 U+ q5 |                                +($signed({3'b000, O[ 0][+1]})        //+2* O[ 0][+1]
9 \& B( M, }! G* ^0 t& ]                                                <<1). V; _/ L9 z+ h3 c! Y
                                       
# e- M6 u1 |8 k6 K+ ~; k. f                                -$signed({3'b000, O[+1][-1]})        //-1* O[+1][-1]5 U, K" T% D/ H& Q
                                +$signed({3'b000, O[+1][+1]});        //+1* O[+1][+1]6 `( d5 S  b) @, s+ N1 ^# x& t3 h
                                
; o, Y. t- I* t( e4 K1 W                                7 X4 t  q0 Z( g2 n5 r3 y0 L
                                
% z8 `' r; p. _( ~/ i+ I: G: |                Dy        <= $signed({3'b000, O[-1][-1]})            //+1* O[-1][-1]; Y6 j' e0 ?) }! s' D- L
                                +($signed({3'b000, O[-1][ 0]})        //+2* O[-1][0]2 x9 B  l+ n" k9 X8 j4 c4 X
                                    <<1)                ; w1 {0 j2 b2 z& x# `
                                                     
& U9 f! Q+ M/ P" s                                +$signed({3'b000, O[-1][+1]})        //+1* O[-1][+1]* I. ~9 }! b( Q, C. N- k& a+ _6 x
                                -$signed({3'b000, O[+1][-1]})   //-1* O[+1][-1]# Q1 `! W& O/ z6 H- [, e6 U
                                -($signed({3'b000, O[+1][ 0]})        //-2* O[+1][ 0]
8 @6 k' J" I, x' N* ?& |: }                                         <<1)5 Q4 V8 d2 _. }% s9 _+ I- Q! \. ^: T
                                        2 Y  W, |2 ^  F  i) }4 e4 |1 G
                                -$signed({3'b000, O[+1][+1]});        //-1* O[+1][+1]
3 _& A" q# c4 H4 x% K) ^' g                                
1 ?0 J- r/ C% e        O[-1][-1]        <=        O[-1][0];
9 [  z' D4 s/ U  }        O[-1][ 0]        <=        O[-1][+1];
" h6 w* M3 l! p- H, z5 e1 U        O[-1][+1]        <=        prev_row[31:24];8 G3 h: P' v, |8 H
        O[ 0][-1]        <=        O[0][0];
' A# I* V2 F$ S        O[ 0][ 0]        <=        O[0][+1];3 Z0 \5 Q, u9 M' d' {0 w  T0 G
        O[ 0][+1]        <=        curr_row[31:24];$ y, q' n- }' W9 C
        O[+1][-1]        <=        O[+1][0];
% C. V* ]8 \# y: h* A* J  T2 h        O[+1][ 0]        <=        O[+1][+1];6 N0 k, H5 j% p: h
        O[+1][+1]        <=        next_row[31:24];* R2 D9 e6 F3 w4 G5 i& t
end3 Z0 ]9 G$ D1 B9 ~0 ^1 s; z
/***********************��ֵ����***********************/
! J5 \/ }) ]5 t! N//assign D1 = abs_D < 60 ? 0 : abs_D  ;(����ijЩͼ�����б�Ҫʱ�����ã���ֵ60�ǿ��Ը��ĵģ��������ͼ��������)
/ \$ Z/ Z" b/ l) [/*****************************************************/
2 }6 F4 F2 e7 A- U% e9 q, }" _7 xalways        @(posedge clk_i)
$ f$ h8 v4 o8 m        if(shift_en)        + e1 i/ T* c  z2 h
           result_row        <= { result_row[23:0],/*D1*/abs_D};  W# |! I' d9 s' m
endmodule2 O$ H6 t; ~# c8 w1 _0 x5 C
: r; K; T" F1 z7 ]8 N/ w

* t/ E, }; ^' I8 V8 u  _, N5 Bmachine.v$ _- z' F% G+ L' J$ z: z

+ ]7 G) M% P  m8 N' z) X, g# [0 G' u( }! d, t$ T

1 t9 k' H' X. X`timescale 10ns/10ns
  D/ f3 l" I9 g% u% {5 N" N/*****************FSM***********************/
' U+ a: {" {9 K, F6 N! Dmodule machine(
4 s( t% B: O/ ~: U% y               //input
* s4 u+ Z$ E) m% l3 D( t1 Q' Q. x8 V               clk_i,
- s( o( e5 {$ F4 d& ~% E               rst_i,
7 e' j6 s0 t" Q1 Q6 q               ack_i,
% }6 _$ ~( X, |               start,
1 X+ T  H5 T$ m( v' l               //output
9 Y3 y! d) G- J  b, A               offset_reset,+ J7 p% H* I0 d) @
               O_offset_cnt_en,2 D. l. [# Q' J! i
               D_offset_cnt_en,
8 [6 v% d% [! P: s- Y3 Q               prev_row_load,
9 i. G- e% s1 n! e0 h5 T! y7 ~               curr_row_load,$ J  K* V1 |& M. U7 `; S# S+ c( H
               next_row_load,
3 _/ B8 @- H* k9 H. t9 F               shift_en,
: H# a) }6 W$ d$ n5 h2 |. S7 P+ x               cyc_o,
* x" u, s' l! V  |- u               we_o,3 K$ ]0 F3 c6 h/ t2 t# U* Z0 t
               stb_o,5 k* C# @" N7 u3 Y
               current_state,
  g# Y9 l9 S1 o               done_set
- t0 U% L3 k- x& h4 j% s# J( v               );. l5 O6 y: V2 L; ?/ ~1 A0 r& P4 D
input  clk_i;" B4 M& T% f" F: b4 N
input  rst_i;
8 w# I6 \4 B- n& T" o; |input  ack_i;( H6 v% z: C" i& H+ b
input  start;
( I- D) m9 d3 m5 L0 [output  offset_reset;
8 X/ x: A5 o% A* Koutput  O_offset_cnt_en;8 K/ a  V' R5 g# r) b# w
output  D_offset_cnt_en;2 ?: f2 M8 p) \4 G! h
output  prev_row_load;        
! k+ C+ q6 n) Xoutput  curr_row_load;      
1 w3 D  ]- B# zoutput  next_row_load;    6 G3 R; L+ r% \* ]  {
output  shift_en;
/ v5 j/ }: p" y7 E; Aoutput  cyc_o;3 U0 g/ ^! Z) q8 g
output  we_o;
3 h$ I/ H  C0 n2 r8 a2 [output  stb_o;1 t, z- s- p0 B3 I+ c& Z
output[4:0]  current_state;) F3 d2 M8 e# p. ^/ v
output  done_set;% h$ E7 \; v6 O4 M. z
) y& u( P" j  L
parameter WIDTH = 1024;  2 r& ?& K3 _7 e  u, Y+ Q4 e
parameter HEIGHT = 768;
& s/ p* ]& q: N- W/ G* L% a1 c5 { . x6 v" B0 O7 N
parameter [4:0]        idle        =5'b00000,
  I8 {8 f* q" ]. H$ P. w7 {9 H% x                                        read_prev_0        =5'b00001,
% R# V7 h+ i6 ^. u                                        read_curr_0        =5'b00010,
- F' a# H9 Z3 i                                        read_next_0        =5'b00011,
3 Y' V1 O/ J' I: q" z! i6 K                                        comp1_0                =5'b00100,
+ v0 R* _" W! X; ~- _4 h          comp2_0                =5'b00101,
# @7 `. p9 c( s& s2 [/ R8 K) K                                        comp3_0                =5'b00110,$ l, e- ~5 A/ q% U, R2 e: e) K
                                        comp4_0                =5'b00111,( L# K: ?" |# ~7 X5 D+ @
                                        read_prev                =5'b01000,% c+ v* M8 J! `4 {& K
                                        read_curr                =5'b01001,2 ^3 t0 g8 F. M- c9 z! E7 h# }, Y
                                        read_next                =5'b01010,8 F( C! V9 Y8 Q; s
                                        comp1                        =5'b01011,
' G. I. h' w/ Y0 L                                        comp2                        =5'b01100,
' h1 G* Y7 F6 E" [& ~  B. U" W, f                                        comp3                        =5'b01101,
9 h* s+ L9 n/ c  a0 e2 r$ T5 l. q                                        comp4                        =5'b01110,* V* r6 X8 H  U) U
                                        write_result        =5'b01111,* U/ v" x0 @3 Z) {: p
                                        write_158                =5'b10000,6 T5 q! {! ?- |8 R  L' D4 D+ E* t
                                        comp1_159                =5'b10001," \( z0 O% ]0 z  X+ K+ r
                                        comp2_159                =5'b10010,# q& j. q; O( [. l0 g5 F* @  }
                                        comp3_159                =5'b10011,
7 `& r( B  g$ ^5 q; k; \9 [$ h                                        comp4_159                =5'b10100,
' C" x0 L" N0 B1 c                                        write_159                =5'b10101;
! H7 F0 v& ^, M2 j                                       
0 V: }# C, p# Yreg [4:0] current_state,next_state;3 S  S$ Z' b$ o  q7 b
reg [10:0] row;    //0 ~ 477;
$ A% [0 a+ E% ]% e6 e2 ureg [8:0] col;    //0 ~ 159;4 U5 O5 x. V' B+ B
) o3 {; O9 l$ Z; F4 V. C" Y
wire start;
# |# l8 @0 g6 K, Q) Kwire stb_o;
3 g- C4 W9 |3 J6 c) breg  offset_reset,row_reset,col_reset;: L  i$ G0 G! N/ {/ i" @5 @

6 p. q$ b2 W4 K+ \: b( {9 V) B* wreg prev_row_load, curr_row_load, next_row_load;! g% P- [# O+ I. S
reg shift_en;
! ]$ J* i+ N# A4 Ireg cyc_o,we_o;, n, r8 ?' l) P& ^; V
reg row_cnt_en, col_cnt_en;2 B) ]4 }5 ^- Z1 o, r0 e
reg O_offset_cnt_en, D_offset_cnt_en;
: A! U2 P" C' i0 A. h  sreg int_en, done_set, done;2 R0 T2 O2 N# h3 W4 r* j

/ y& G$ z4 r: z3 X) V
( u- u3 R$ W9 e% I0 L8 I
: X& ~- x0 s, l' f& v1 w/ walways @(posedge clk_i)                //Row counter
: Z4 v& u! [4 G, F        if (row_reset)        
% B* S% u8 n: S% d3 z% o6 e" x7 P: n                 row <= 0;
  l2 G: f4 R# i6 T" `! f! q        else 2 M7 E$ r; P2 w  g# [2 j4 v" d
         if (row_cnt_en)        : T; p5 h1 J6 }! ~: m" n: m
            row <= row + 1;
* r( y& d8 L- D( V( i8 R  d, g
  G, p9 t9 M# `6 K' G9 ualways @(posedge clk_i)                //Column counter8 w3 Q% E* N3 t
        if (col_reset)                : Z$ m( }2 ?5 a9 z+ ^
           col                <= 0;# M% v, ]$ h/ c  o0 n
        else
, E* H6 n, l. c# r" q; a          if (col_cnt_en)          Y3 o1 W3 [, r2 O2 H/ o; C- e5 n
            col<= col+1;1 r( {$ U, b' X: k2 }
* t5 V6 I0 |. w% i
//fsm
, b2 @! y9 r2 P8 q; Q/ V$ Valways @(posedge clk_i)                //State register4 M3 n, n9 ]' T. Y
        if (rst_i)        / S3 s9 o/ @9 F
           current_state<= idle;2 ?& k0 f6 |# ?/ @( J7 ?5 P- ~* P
        else        : H( [3 l  y( f" o2 t4 [0 g2 M
           current_state<= next_state;
+ {( H" }$ |$ m$ N" d/ T        : K6 B9 p: |9 x4 g" c9 }; P
always @* ' O+ K3 B4 X9 l# \! a: x6 Q1 |
  begin        ) ^6 P. j7 U- V
        offset_reset                =1'b0;
& X+ W$ p& u7 N1 g* H  row_reset                        =1'b0;
( q0 ]- [" p' _3 h! y" r6 t        col_reset                        =1'b0;1 D. o$ q" k/ {8 ~
        row_cnt_en                =1'b0; $ D  X& p, ^% a1 Y
        col_cnt_en                =1'b0;
2 T8 X  k7 p4 w$ w3 K! \: Z        O_offset_cnt_en        =1'b0; 3 e& R8 _. Y+ r8 r) W9 u
        D_offset_cnt_en        =1'b0;6 j; o! ~  `% O0 m8 I+ s1 t1 Z
        prev_row_load                =1'b0;
7 P$ N' _) \; r6 t1 ]0 v        curr_row_load        =1'b0;
( }1 m5 C3 M5 e  q$ t        next_row_load                =1'b0;3 Z# h) p, s# g$ p
        shift_en                        =1'b0;
5 v8 k5 w/ [$ ]# J! m. d+ L        cyc_o                                =1'b0;
7 \) |' L3 V( t        we_o                                =1'b0; 0 U7 |4 u6 b% l
        done_set                        =1'b0;
1 Z8 v, K) `: V+ m        - U* Q9 d9 a: _5 U4 z: W' t% j! V
case (current_state)
& ]% P* G2 D- V: o- B4 Zidle: begin  S. H: O" ?. M+ {
            cyc_o =1'b0;0 M* j, x; ^/ C, g* i4 ^& b" x
                        we_o =1'b0;
% y" \" z& M) T                        done_set=1'b0;
4 h3 }( c1 E" s; e! V( a7 k3 O& L% W                        D_offset_cnt_en =1'b0;% _5 c. a3 r' c* N
                        offset_reset =1'b1; ) q# V2 u9 Q# k+ A
                        row_reset =1'b1;  \5 b' F! Q5 |3 J8 y0 x7 q( s
                        col_reset = 1'b1;) h4 q9 h. o! I0 A
                        if (start)  ; |& }" T) _% b) }+ ]7 x9 _' c
                          next_state = read_prev_0;' A- J1 I% |! p: a
                        else                 4 Y% E) n. Y/ k( G6 G3 C
                          next_state = idle;+ I' ]6 ?" m6 D2 p' A( d- s
      end3 Z/ I0 z9 F8 S
         
/ D) `2 C5 @6 t9 m- P/*************************************************************/         
# H1 ?6 E4 J4 Sread_prev_0: begin' e+ l+ d0 `4 j! y5 A, Z
            offset_reset =1'b0;
/ O% S( y: x8 T4 v! z            row_reset =1'b0;
( o( f' u& K. T; S            we_o =1'b0;2 `4 j5 L# p1 v+ r
            row_cnt_en =1'b0;
' T$ E. R" v, @/ n            D_offset_cnt_en =1'b0;) U7 ^$ O& g' V* `) D
                        col_reset = 1'b1;   ]; T3 `. t0 u- K7 v3 O
                        prev_row_load = 1'b1;+ e, K% d* z4 d# l- \5 q- `5 z
                        cyc_o        = 1'b1;
$ F  y+ r. ?$ C( k$ Z                        if (ack_i)  4 m8 N$ z; P' \7 D, k
                           next_state = read_curr_0;
2 y( h9 M- h+ ?, w                        else        6 v' `" u0 K5 ?3 U; [; o7 F# O
                         next_state = read_prev_0;' d* n% \9 ]3 X. `4 y* C
                  end
( B3 d5 |6 v' l' `/***********************************************************************/                  
3 r" l" w; V$ Cread_curr_0: begin
' A) c1 f5 V# g1 G" l. @" L7 s3 s            col_reset = 1'b0;
2 W( ~! R: _+ s# I& G; V& S: E4 ]: |            prev_row_load = 1'b0;          \( o8 {& ]* V# b8 T0 M0 X
                         curr_row_load =1'b1; 1 E6 i7 f/ V: v& w; W2 s
                         cyc_o =1'b1;6 v, y- o6 q2 E4 c; `1 n
                        if (ack_i)              //read mem& o; a' N+ T7 \
                           next_state = read_next_0;
6 `: D( ~- U: g$ W) w                        else                 
5 T9 x# |" s# ?3 n                           next_state = read_curr_0;
0 r% l6 t! ^' g- N9 _+ ~& t& [                  end
9 }. {* W, I* _# n0 ^/*********************************************************************/6 W* r" B% ]! S! q- Z7 q4 N
read_next_0: begin
. s4 {0 M/ v3 d# g* |            curr_row_load =1'b0;3 z  ]4 G1 n: E1 ~, B# N
                        next_row_load =1'b1;
) s$ G- m+ ?% @, S                        cyc_o =1'b1;, K4 B6 B2 e' E) ~& t/ A  [" J
                        if (ack_i)                    //read mem��cnt+=1
- C, V. M' E" d; F                          begin
$ E) a" K. X& W  s0 P0 k" M                                  O_offset_cnt_en =1'b1;
7 E1 O% V5 P8 ^7 }% i                                  next_state =comp1_0;
% |6 C4 p. q/ ^  f9 S                          end) J) ]+ l& X% u& c0 ], ^
                        else 5 @; d: B8 k; [; `) {) r
                           next_state = read_next_0;- J1 j1 ]1 a  G! P( u7 t
                  end3 `& c) @" K9 C3 o; S4 |7 i
/********************************************************************/
/ v* V3 C" ]1 h( M/ s9 H- H8 ncomp1_0: begin
4 w# {9 ~$ ~: W            next_row_load =1'b0; 2 R6 G: }  M, b: t" R( _
            cyc_o =1'b0;+ D  Z, n. ?! [* |+ N
            O_offset_cnt_en =1'b0;/ L& [, O+ ?0 N4 z: |
                        shift_en =1'b1;
$ V7 U" E( I& ]                        next_state =comp2_0;' e! x6 I+ q1 o9 w1 a
                  end- p4 D4 H2 K9 X
comp2_0: begin
, t- a6 G! E: d+ H9 n6 @                        shift_en =1'b1;
7 E5 Y: k! S& u& _# n! T& Q                        next_state =comp3_0;* J% n+ o6 |& F$ X/ ~, Z- z
                  end
- g- G& H) w+ m6 fcomp3_0: begin
+ N, _5 n# A' [                        shift_en =1'b1;
, X3 Q: v( A  a& ?4 u. }1 U                        next_state =comp4_0;
- O! U6 E) C! H8 R( ?2 {+ x                  end
! M- n4 U$ ]2 o( o  Z( gcomp4_0: begin
6 \% @) \! n- i2 Z) p                        shift_en =1'b1;
& d3 p% o1 x: x- K8 C5 W                        next_state =read_prev;
0 d# G2 z, L" n; W                  end        7 [3 n8 c. v8 P% H7 ]! z# Z7 b
/**************************************************************/
% e. O* H1 ]' M$ b- G& yread_prev: begin
. m+ m9 M. \" K7 n! f            shift_en =1'b0;        
) x1 c, e4 M- P$ H- U0 k            we_o =1'b0;
, L$ H# u! d3 I  D            col_cnt_en =1'b0;
' P9 q1 J' P! z8 f            D_offset_cnt_en =1'b0;
- G/ E3 c( a5 \3 @3 K6 h                        prev_row_load = 1'b1;* D/ d' S1 ?1 \' s2 ?& E3 `- R# R
                        cyc_o        = 1'b1;% i% w% M2 L% \! r5 L8 ~
                        if (ack_i)  3 H$ `: K. }: t: _0 F0 ]
                           next_state = read_curr;$ ]! P2 f( L# n2 _2 h, t# |
                        else        
$ ^* t' u  ^$ E% y" G                         next_state = read_prev;
, `" D# _3 G: F4 h3 P: q                  end           
" a- ^  ]1 ]  b8 hread_curr: begin        & L7 l$ \; f: i; G
            prev_row_load = 1'b0;. _8 r! o: b0 o: {
            curr_row_load = 1'b1;/ f, K6 Z) ~! s* Q) ~5 k3 P: c
                        cyc_o        = 1'b1;! z; i- T+ T5 Q2 `% v
                        if (ack_i)  
1 O8 l. `% k6 @& f9 _5 [. M                           next_state = read_next;$ q. e4 A4 A4 O( H1 ?7 }/ o
                        else        1 x) S0 f4 Q6 G8 f8 M
                         next_state = read_curr;; \7 l. ?6 O" v( s5 r
                  end        
' N, t( P, M2 j9 mread_next: begin: L9 T0 r3 I, d* y
            curr_row_load = 1'b0;        
" A9 e3 h0 U) L7 Y, f            next_row_load =1'b1;
! u6 ?, [" Z$ S5 L' P1 Z                        cyc_o        = 1'b1;
' g, K/ [% v* @( A                        if (ack_i)
7 e: k8 l. {$ u( M  L                                 begin: \) U1 d* N0 k; t" f
                                          O_offset_cnt_en =1'b1;  
. p  ?5 b" j, ]/ O' V% S                             next_state = comp1;$ Y8 n9 l4 U7 k. F
                           end
6 R+ E- C/ o; ?2 @                        else        7 z5 F, l* B9 ^4 A- M
                            next_state = read_next;
0 h1 i: \1 w4 S2 G: L. e                  end8 g1 j" R6 y5 n" W9 E2 s2 s7 K
/************************************************************/                  : U" F) R- I2 X# E2 r
comp1: begin& C% T; }8 t9 U
            next_row_load =1'b0;* d) P; Z& s! j0 ^. e
            O_offset_cnt_en =1'b0; . r, X; j7 X* }+ T3 S' |
            cyc_o =1'b0;" h% }8 S& ~0 x; ^3 F( k
                        shift_en =1'b1;1 z& r1 i0 o3 ]& t9 F) I
                        next_state =comp2;
4 `/ B0 a. l2 j6 e                  end                   . q" Y% b; @" @" ?& M6 ?
comp2: begin( }" t" Q& G% O" w. `" l
                        shift_en =1'b1;% G9 T1 R& q# i$ P8 V
                        next_state =comp3;
* q- C% v* w' Z, l/ S                  end4 e6 F! ?" }9 O; W, r
comp3: begin
# c+ H$ f7 t: L; f* f$ ~# |                        shift_en =1'b1;
! O: A( G  L5 z7 S; {( v/ T                        next_state =comp4;  o# j" Y- A% v
                  end                  
; [* P& q9 h8 c% [+ Qcomp4: begin
5 a" A" z( K2 n: g- J" m" n5 O0 H                        shift_en =1'b1;
( v5 j) i; ?% L8 c7 u5 V& N- t" f7 F# N                        if (col ==(WIDTH/4-2)) 5 w' l5 E2 g! M- Z6 }- S9 o# h
                            next_state = write_158;6 y. f- q+ h% n! h# k  F9 [+ J- N" s7 D
                        else                        
# t7 a+ A- O" L: o  e0 l4 A                            next_state =        write_result;
% v" X6 {! s! t" V5 ], i! H                        end
( Q. T4 R- G) }! c/********************************************************/6 J% U! `5 q* J2 Y/ W. t
write_result: begin
6 s: V/ b5 c5 w            shift_en =1'b0;; a: F9 H$ a7 h9 |
                        cyc_o =1'b1;
6 }9 W; o% k. {% l( L7 P                        we_o =1'b1;
7 ^+ v% o( t6 i" W                        if(ack_i)        3 n% P% c0 r! Z& x) H1 F
                          begin
- D# b# o, z% N5 `# s+ ~                                  col_cnt_en =1'b1;
9 d/ I6 |: ~: {. U7 |2 f) V) @$ b% {                                  D_offset_cnt_en =1'b1;1 t6 T" A5 K/ Z# {, m
                                  next_state =read_prev;5 P, |) F. h2 B
                          end; L' O3 J/ x# H3 S6 K
                        else
, a' [6 L9 G0 Y& C; M                           next_state = write_result;: {6 D! m8 z2 y; b4 T  L
                          end+ b$ o  j: D& v4 f
write_158: begin
' m, l4 S8 V3 r4 R            shift_en =1'b0;) Y* ^2 W$ h% i0 i
                        cyc_o =1'b1; ' {; s0 S, R2 W2 S3 E8 L+ Z& P: h. R
                        we_o =1'b1;7 J9 f) U; L9 l, W8 |
                        if(ack_i)        
0 I; _  W! i3 _  z+ t                          begin
+ H/ {# M3 I# A$ t* J  n  m/ p. {                                  col_cnt_en =1'b1;
. h' q& K9 j9 C! T- S0 P+ p                                  D_offset_cnt_en =1'b1;) q% Z, h2 x7 z, ]2 k
                                  next_state =comp1_159;
6 y% Q+ x0 s6 c$ V! e0 [                          end
+ @/ X! z8 Q" @5 S                        else : k+ S/ ~9 ?- r# [' r4 @8 |0 g& g" Y! ^, v  E
                            next_state =write_158;
, G3 |; ?/ N( D2 @# s                        end% ^! y' ]( @5 Z% f9 E/ ?$ y
/***************************************************************/
* _8 T( N( Z9 s( Z  v& ?* Icomp1_159: begin                              //pipeline output stage
# H2 N* o, S( z7 \, ]            col_cnt_en =1'b0;
5 Q, b9 c  x, k            D_offset_cnt_en =1'b0;
1 B  ~6 {" @8 n, N# R4 Y0 d7 v            cyc_o =1'b0;$ j6 {$ m: T3 ]  ^! y* a, U  M
            we_o =1'b0;4 \3 R$ n9 V3 ^; M$ _$ _
                        shift_en =1'b1;# T* A# S; ?' b  q) s! c. W. @
                        next_state =comp2_159;0 U3 V" V: ?& Q* J
                  end                        
. @! V, I0 {, i" v5 M  Kcomp2_159: begin
1 u! f/ J( m$ K7 i4 @$ a9 b            shift_en =1'b1;
" C2 w  T% [% C* |6 u                        next_state =comp3_159;/ n- l* v3 h3 {9 {: K
                  end                                
1 J- d, x" P: A$ z! z' t( {" z- ccomp3_159: begin
1 o: y" P- }% g5 A            shift_en =1'b1;
& R% _5 s0 r/ {0 A3 c4 h                        next_state =comp4_159;
) \/ d; X8 z) Y9 W; b) c                  end        
& f7 S  g/ O; s1 Q1 acomp4_159: begin- q& ]% P) k5 _& D0 ?1 f
            shift_en =1'b1;
/ O1 \4 G' H# p' J( A. E. s3 F$ h                        next_state =write_159;1 O+ b3 Q. S# P: v$ F  W1 e
                  end                                                  
$ B. u& J  B4 h' gwrite_159: begin( O9 V  A) l! Q2 V: Q# p& ~
            shift_en =1'b0;- a% `( ^* ^; p1 J, c& @' i
                        cyc_o =1'b1;
0 e+ r, s* M6 }9 O4 V) \! ?" e. U                        we_o =1'b1;7 o: a) {$ V2 F, y' S2 t7 s
                        if(ack_i)        $ r/ U* \9 v8 _# ?* F4 n/ u  X
                          begin+ N  @: Y5 F+ f- D0 g) _
                                D_offset_cnt_en =1'b1;
! i4 [  K) a6 Y, ?7 X% V$ q4 j                                if (row == HEIGHT-3) //sobel done
$ l) E$ c; S7 m+ P- Q0 o                                   begin) I0 `) E% C4 c2 p- p. c
                                           done_set =1'b1;
( Z+ U* d% Z6 s2 J                                           next_state = idle;
! K$ F) f3 z: r# K) g7 o                                   end
9 n: l2 y! W( s+ L; S$ Y5 a9 ^                                else + B2 t6 ~0 c- ?7 [
                                  begin8 y8 H( ]+ i( q: p' Z$ E' |
                                          row_cnt_en =1'b1;
% G# x  \% p& Q7 E3 j                                          next_state =read_prev_0;
3 u/ I/ a6 q( m: L                                        end
* T: |) q" }8 r) v) K                         end, i& x0 P* s4 w( ~3 k
                        else
8 k! {$ \" }4 v3 v2 B                           next_state = write_159;
# p7 G0 Q. C! s6 P. q. e# G                        end) E) u$ V3 i* Z$ @
        endcase: `  C* @% C9 ]& ~7 k' g& u
end
- ^" n1 h( \' ?- m9 |2 n/*******************************************************************/" Z' L0 M3 P& m  r7 }
: S3 t* C, ~* x; f
assign stb_o = cyc_o;
  s5 u" `; z5 F4 W $ `8 r' o  D" D1 I
endmodule
; ~& y1 _( q  [5 M* Q
3 @" W' O" B7 \! A
, {7 F# o1 H( s% T5 Fsobel_slave.v8 Z' w5 s. b! i& M, t: r
' D- i& D1 I: S. J4 t$ U$ Q3 k
9 J- \3 D' B4 B& S
9 ?9 n6 x% R7 y
`timescale 10ns/10ns( F! S  Z& ?  k
module sobel_slave(: @7 G% x) U$ g2 f9 c
                 //master slave share i/f
' e1 u: r6 C# g- S! J$ H( T                 clk_i,
( T. `* n) p! R! H. F# Y( A                 rst_i,& X5 H  t1 G# Y5 q
                 dat_i,
7 g) h3 J8 S, [5 C5 k7 @                 dat_o,              7 X' ~* m+ {6 G$ [) w1 d0 W2 {; y
                 //slave i/f# L% a& q4 j. q& D" Q
                 cyc_i,
( j; ?1 y# j2 O' H9 t                 stb_i,1 P1 F' G& `. x$ Z4 h
                 we_i,: x0 ?  \1 K- o$ z$ Z
                 adr_i,
/ J% W$ v# C& h' i- v4 R9 ^6 O' \, ?                 ack_o,0 U4 G* b/ k+ M/ @. {
                 //output
) c& ]$ [% x1 G9 j$ \' u                 start,! F! C7 O/ Z6 T* T9 y9 }- x
                 O_base_ce,
9 t8 o0 Y2 u( }/ M# Y% g3 B% S                 D_base_ce,
4 S: e2 o2 `3 e/ L  b                 ; s; u$ j- E3 A6 b- I! I# e/ q
                 int_req,: q2 n$ B# v! Y! l* s
                 4 I# J" k  O$ x. b2 J; L
                 //input  C" F- Z. f4 ^. E
                 done_set,5 Q6 _5 t5 l5 z, o: a$ @9 |
                 result_row
; q0 o7 m! A1 y5 G) d4 k4 E                 );0 u* i+ e. d. J8 `' o6 a2 O% D) t, C: Z
                 
- x  U/ I! |9 cinput  clk_i;
0 d. {) i7 U# x6 f2 {input  rst_i;
6 j. K+ m8 P: }8 [input[31:0]   dat_i;" C9 P& A# y1 D. {% J
output[31:0]  dat_o;* ~* r6 D. n# g' Y
3 h0 l& {* W0 k: D  P2 {  t
input    cyc_i;
" i6 ?5 E5 d% C8 V, M+ k( n# e( n& Ainput    stb_i;" l# N; B7 Y, v4 V4 S( J9 Q. g& n
input    we_i;
3 s9 ~5 v! c; A# @$ v+ w! E% f, |input[21:0]    adr_i;
# t4 |3 U8 c1 d8 d# P. Ooutput   ack_o;5 @5 ^1 ~# H$ ?) I3 ^7 i
output   start;
" n" s% W7 t9 O+ n3 L7 Voutput   O_base_ce;- }, V( k% D. m6 g/ M- ]/ a
output   D_base_ce;
% P  r# i$ K2 j/ L' }' qoutput   int_req;
, w* Y6 \5 h+ x: m, L$ ~2 c$ ~input    done_set;
% {$ w  F& O+ I) k4 Binput[31:0]   result_row;/ p* e. E3 }) ^3 r# w( }- ^: P% m

* t& o/ f% E! {3 Qreg int_en;
% l& Q6 L$ S& p! N: u9 `' Treg done;
; c! m/ b( s' R$ breg ack_o;$ I6 q* ]2 l/ |. Y$ R  o/ N
reg[31:0]  dat_o ;   
& [9 M- P: R! C' [
4 n8 k' n/ S: T5 {9 v/*****************************************************************/6 S& V; V3 O* O8 y8 V; p$ T) V
            / w# m0 v0 j9 R* T
assign        start                = cyc_i && stb_i && we_i && adr_i[3:2] ==2'b01;//adr_i[3:2]+ A; U3 x+ i1 S0 J) i" c  x: u2 r
# t1 j' [! W8 i4 ^% Y
assign O_base_ce        = cyc_i && stb_i && we_i && adr_i[3:2] ==2'b10;8 g+ h& n3 Q3 l2 X( F1 {) c
9 r* ^9 F) ?/ Q+ a" |6 F  n
assign D_base_ce        = cyc_i && stb_i && we_i && adr_i[3:2] ==2'b11;* p. S. K) A- r, l/ O' H
: J# N6 q0 o0 K8 R, f
/*************************************************************/
9 B2 v) W2 a: H3 W7 ~2 X
- @" N  U, w2 o1 Y+ B2 n// Wishbone slave i/f
! L, r- Z$ f' ]3 P7 k; H! a) k7 i
" C7 M7 u( \9 C! B3 p, X6 p( Lalways @(posedge clk_i)//interrupt reg" S, Y) o1 j+ ?
        if (rst_i)
7 \+ ^1 y/ O" x. p# g                int_en <= 1'b0;3 S  ~- y) v: N2 a
        else $ }/ r/ M9 o2 R/ y, q* [
            if (cyc_i && stb_i && we_i && adr_i[3:2] ==2'b00)
- N3 K* B, p0 t- r6 J                    int_en <= dat_i[0];; W$ [+ F2 G/ A& s. ]+ Q5 O
/*****************************************************************************/                        
# P% V7 h# M( h) H! }  o( g                        ; F- ?/ P, c, K3 s
always @(posedge clk_i)        //status reg
% L6 [" l, u* f( g        if (rst_i)
# {. K7 l0 h! S: `                done <=1'b0;8 E- V! ^4 q; K& |- w
        else
7 T, W4 t3 N: _7 [4 o          if (done_set)
+ p5 r4 A. t+ c4 n4 K# s8 M                // This occurs when last write is acknowledged,, |: `8 ^( k) Q  H3 B- [/ {
                // and so cannot coincide with a read of the
8 c& C" j( W, y7 H$ P                //        status register4 P1 J' R4 ]1 L, o
                   done <=1'b1;+ x5 `1 f* B3 C/ _) Y
    else
; C+ K1 T  }" N% l& P      if (cyc_i && stb_i && !we_i && adr_i[3:2] ==2'b00 && ack_o)( t& p$ N* g& H5 h7 @  e. y5 c8 {; H, v
                done <=1'b0;
* g5 N$ G" u5 K0 f% e' ~                        ) X) W& k4 y7 b8 |9 b
/********************************************************************/                        
& R2 D' @$ L2 p; A- \  W                        % l1 U$ W: _( p  j4 O7 j+ A; q
assign int_req = int_en && done;
. N, o, J& e$ T/*********************************************************************/: Y) ?3 `" ]9 d. Y9 @
always @(posedge clk_i)
. f! y' L: w7 U1 X        ack_o <= cyc_i && stb_i && !ack_o;/ Z! b4 `- A( @
/*********************************************************************/        
' R! g4 t8 M) |* h( c! p5 Qalways @*! ?8 w5 `% e" ~+ @
        if (cyc_i && stb_i && !we_i)5 H/ x8 U  F6 }, l
                if (adr_i[3:2] == 2'b00)/ O% C) {- Z- i) R
                        dat_o = {31'b0,done};// status register read
4 G9 R* X" B2 R( b                else9 r) l; ]* i* T% f9 m- }1 }! M1 ?" Z
                        dat_o = 32'b0;        // other registers read as 0
- }/ k6 {+ m0 }# }, d        else
" d( O; c. U. u. T( q6 B$ @                        dat_o = result_row;        // for master write
! V' K1 z. M& S7 j3 ]8 W* Jendmodule                          w# l% }6 J. R; G; C+ d- H
( M/ Q' m! e- z$ o4 x

# y+ {! N- m. b, m7 x3 q. s* l2 o. t3,硬件的功能仿真
$ s$ C" m. W. q0 Q- w4 Q5 s& i在进行仿真之前,我们需要编写相应的仿真模型和相应的图片预处理,后处理程序。
. z4 C/ Z; b: l! `3 j* F, j1 K
) v- a2 Z* \0 _5 {$ N下面是前仿真的结果:从中我们可以看出硬件的执行时间是23562270个cycle,约23.56ms。0 l8 X0 K9 G0 \
' h5 W" o" Q7 \  G. a6 q" o' Q& l
- h) ?  m( N2 Q7 S, m* v

6 s) q; R3 R/ r  {/ p8 p& {# f" `
4 u# y: Y& r& |0 ^* d
在做功能仿真时,我们就可以得到一个处理结果了,原图和sobel处理结果对比如下:) r2 f) r9 L5 U6 H; ^

+ X# b' ?4 z) Q. x4 _3 U0 \ 9 E( I; g7 A. m+ M/ f9 k
+ F% N2 _" Z7 q( T

, v2 l) f5 |7 d6 E- @) I# J; j$ c7 L. h
功能仿真的具体操作步骤,请参考bmp_post目录下的README文件。内容如下:1 j* ]5 ~" N# D/ t9 v
7 n# n! e4 q+ {  l9 i* U; c

; J! p% J, A3 `0 m$ ~+ \8 |
8 H' Y9 W2 R0 x; v6 ?/*% t" f# {2 G" p" d
* Rill create
1 Z+ ~) F1 b6 F7 y* rillzhen@gmail.com9 o+ i; V7 U2 x
*/; y! E% y( S# S
. }8 N2 e; F, j& q- u5 W# W
1,保证原图为1024x768的8-bit的sobel.bmp+ V- j3 x8 r7 H" I  H$ H0 H
2,运行read_bmp.exe,生成bmp_dat.txt
" I* z. t; X3 @; X# K3 L2 `2 S3,将bmp_dat.txt复制到verilog工作目录,运行仿真,生成post_process_dat.txt: F* m# }6 A9 N8 o$ m  g
4,将post_process_dat.txt复制到本目录,先运行bmp_process.exe,保持bmp_process.exe运行状态,再执行bmp_bin.exe,最终生成sobel_rst1.bmp,为最终处理结果。
  P  s# v; N. y- |) I
! T1 I% J$ E) V9 I
+ J9 ?( N$ h+ B4 x) F2 n需要注意的是,本例中处理的图片为1024x768的8-bit的bmp文件,如果想处理其他尺寸的bmp文件,需要修改一下testbench.v中的相关内容即可,如果想处理其他格式的图片,则需要重新编写对应的图片预处理,后处理程序。! _# t4 q5 Y$ y( }: X5 X* R# y
+ K3 D0 Y+ z2 ]7 m3 V: C
3 c6 c. i  L$ a

% r. C. H3 n1 n( X+ b, k8 ^4,硬件的时序仿真& G$ M# B% o- S- S/ _$ t1 }
在最终在FPGA上运行之前,我们还需要做一下时序仿真(后仿),这时就需要用quartusII在综合时生成包含延迟信息的文件(*.vo),还需要quartusII的库。
' i* ]8 x/ |6 Z  B' N, ], s3 b4 o7 D% d" D$ b" c" Z2 t
我们用quartusII将sobel模块的所用可综合文件进行综合,会生成sobel.vo文件和其它vo文件,比如sobel_min_1200mv_0c_fast.vo。. `9 W5 H, Y6 E  r4 W6 [/ r

" w9 ~9 S2 \- f: L在后仿时,用到的quartus的库文件有:cycloneive_atoms.v , altera_primitives.v。6 F6 b! w  V1 E6 c
1 f1 v" |2 a8 X( x& Q: z, F
当然,还需要仿真模型文件:testbench.v ,cpu.v,memory.v,arbiter.v。
. C. {# a' C: v% V# O/ a0 l$ r. |4 A3 I! L

& Z* H" U) M7 Q# L1 c6 }
) F- o; s  g6 E" h经过近半个小时的仿真,结果终于出来了,按照前仿真的步骤,也能得到相同的处理结果。9 T1 D. z5 |. y, N
7 Y' N% M. f" p( y
这里需要注意的是,如果用sobel.vo做后仿时出现hold/setup时序不满足的问题,可以使用sobel_min_1200mv_0c_fast.vo来做后仿。
; Q8 d  x% I6 b( c1 B% j4 A
$ ?6 D2 |* `/ H1 w1 u4 u* ~: G* Q后仿真的工程,我也已上传:
+ e* [9 C, Y  O% o/ x2 h$ M. p: q. e! l  T3 ^
http://download.csdn.net/detail/rill_zhen/6371857
$ J  V5 ], c3 u0 W: K0 C. ^3 G# I# q( n% v0 n

* @6 o  _# S: t+ n" y+ ^9 Q* x( {" c; t6 `7 W8 V
5,软件实现
# k7 G- j& i0 U9 ^) e9 B* H' c& O为了便于对比硬件的加速效果,我们需要编写相应的软件程序,然后在openrisc上运行,得到运行时间。; [6 K; v; \1 U4 ~2 H
! Q4 y. j  Y, x8 Q/ L
下面是C语言实现代码:1 U( _3 w- `) R* L; V& W2 ?& u
) a, v- [' X6 l% T
bmp.c:% ~  q! R8 G- M3 N" F* @& v+ R* K
' P/ C4 t; N7 K, [9 _

4 x/ y9 P- a; S' O! j5 N8 n, m- r
( f: m, Q( r3 m5 }- k5 n#include <string.h>    3 i! ?* E/ x0 D  s' F" ?
#include <math.h>      
9 s: T1 R; X2 h& c# S1 B#include <stdio.h>      
# U( K& s7 V* L8 J/ X#include <stdlib.h>      4 G& o2 f; q$ K: ~" k' d% @3 l
#include <malloc.h>   
" y3 i+ M: x  @#include <sys/timeb.h>  @. J9 O" c; _! c; p* G& \& x) h
#include <time.h>  
8 N% H6 B+ F4 ]- @4 i5 @
. V. }8 P0 v) @9 j' R" @8 f% stypedef  struct {, {/ ?# r  p) X3 \6 [# r
        double  real;
3 s7 @8 C) V! _. I        double  img;' U( b% b: w6 c
        } COMPLEX;: Z! w9 F/ ^: H/ Z- q
typedef struct
) f& i4 O0 ?$ F3 \- y7 u, Y8 ?' W4 U{
' F6 m( P5 }/ x) \# [/ l        long tv_sec;
/ \' p7 f! `. j4 s/ q9 _5 Y        long tv_usec;
% J- O* \8 |/ s} timeval;" l# g: f  S" m6 c" s( Q# ]- R0 k
* I6 v( F- q4 X6 Z& k, J
   
7 y2 P- b* O9 Jtypedef unsigned char BYTE;   
# ?9 O/ E& l: f$ M% g+ X9 @typedef unsigned short WORD;   
* f5 i# \6 D3 h2 C8 q% atypedef unsigned long DWORD;   
3 F' q6 f0 v$ k8 p4 x4 Xtypedef long LONG;   $ F- Z0 N8 e  G/ T7 [
  
5 W+ D  a4 N, J% v/ m9 ^ 5 l' o& I# w5 K* u' A3 W
//位图文件头信息结构定义   
1 J0 E7 _0 v4 h4 a# L( a6 E( v5 q//其中不包含文件类型信息(由于结构体的内存结构决定,要是加了的话将不能正确读取文件信息)   0 }- J% h/ R, Z- N. ?
  1 O% z" q3 G2 D5 P3 Q) S+ q3 i
typedef struct tagBITMAPFILEHEADER {5 V& m2 K9 O4 u8 h! @
        DWORD bfSize;           //文件大小   ( P; q9 Q# q; @! ^/ M' ]: i" ^
        WORD   bfReserved1;     //保留字,不考虑   5 P9 }; h* t, p2 u( z+ N
        WORD   bfReserved2;     //保留字,同上   
' J: [1 g3 l8 g8 J2 U        DWORD bfOffBits;        //实际位图数据的偏移字节数,即前三个部分长度之和   ( V; g3 a1 T& U& ~+ S: c; p/ b- }
} BITMAPFILEHEADER;   
4 }- U9 o' A+ u) u' Q+ L1 K; Z8 u2 \  8 ]4 l, p- z6 F' O# S
  & I3 p" z" L! e" M# U" \0 T
//信息头BITMAPINFOHEADER,也是一个结构,其定义如下:   
/ P2 ~" b4 r3 n% ]9 s  
3 y. o' Z/ w9 P* Rtypedef struct tagBITMAPINFOHEADER{   
6 _( [3 \, q8 y' D: S7 F        DWORD   biSize;             //指定此结构体的长度,为40   , |2 Y" O- m; ]$ f( a
        LONG    biWidth;            //位图宽   8 s! f5 e/ f. k9 ]5 E8 Z. I
        LONG    biHeight;           //位图高   : E9 a0 u" \) m% R7 Z: T# V# O# t
        WORD    biPlanes;           //平面数,为1   
# k% W; I% H" D5 J: e) i/ D        WORD    biBitCount;         //采用颜色位数,可以是1,2,4,8,16,24,新的可以是32   # a+ G9 e6 M7 ^
        DWORD   biCompression;      //压缩方式,可以是0,1,2,其中0表示不压缩   + d9 V" |. {7 q6 D8 B
        DWORD   biSizeImage;        //实际位图数据占用的字节数   , a( K# j; n4 J  S0 {0 F# q
        LONG    biXPelsPerMeter;    //X方向分辨率   
/ v) }0 V7 m8 R) Q' B+ ~! y        LONG    biYPelsPerMeter;    //Y方向分辨率   * F* V0 I3 a5 f& p
        DWORD   biClrUsed;          //使用的颜色数,如果为0,则表示默认值(2^颜色位数)   4 z/ L: R5 a2 r7 q
        DWORD   biClrImportant;     //重要颜色数,如果为0,则表示所有颜色都是重要的   3 j2 l$ s& C! e: G5 h
} BITMAPINFOHEADER;    " F, r# z4 b- B1 l4 P
  3 f/ s* _5 a( x% O7 ?( ?
  
/ r1 N! S. A1 W; I4 Z! ?//调色板Palette,当然,这里是对那些需要调色板的位图文件而言的。24位和32位是不需要调色板的。   
5 K1 K7 N# ^5 k9 u* r4 j7 t//(似乎是调色板结构体个数等于使用的颜色数。)   2 U6 k0 {& r4 p9 b/ ]) g# T
  
/ S4 d0 x8 c) c2 i, ltypedef struct tagRGBQUAD {    ; l7 G  y$ e/ K/ `; A5 I
        BYTE     rgbBlue; //该颜色的蓝色分量   % `% q$ E- }0 K
        BYTE     rgbGreen; //该颜色的绿色分量   ( x2 {0 Z( }8 r
        BYTE     rgbRed; //该颜色的红色分量   
' q! c' a/ J- u/ O$ p        BYTE     rgbReserved; //保留值   
. o' Z1 n# r5 d' s* L$ `3 C} RGBQUAD;   
/ Z' S: J7 O6 l  ( Y$ o5 ~0 ~) W4 \# E
  
' e! o: Y* P/ a6 I8 }. d  8 v, v( [$ Y" w# ?. x3 t2 G: d
void showBmpHead(BITMAPFILEHEADER* pBmpHead)   # `! g& D  N& A' X; r0 o6 a
{   
$ F! K& s. e, V5 L+ _9 m        printf("bmp file head:\n");   
  p; S* C! e7 F5 M/ f8 _* P        printf("size:%d\n",pBmpHead->bfSize);   6 c. I7 v, @& {" B
        printf("reserved byte1:%d\n",pBmpHead->bfReserved1);   
  g5 t6 l: X( |2 R1 t: i        printf("reserved byte2:%d\n",pBmpHead->bfReserved2);   ! F/ E! ], E* b1 D1 P
        printf("offbit:%d\n",pBmpHead->bfOffBits);
, Q' ~: M4 {5 p  J8 ]/ n+ c& r}   / m; b! s7 C5 v5 T6 o# T. K; R
  3 Z# Y: ?0 L" U% U* p/ ~0 j' C
  8 q/ O3 d" D4 C6 d% i* _! b
void showBmpInforHead(BITMAPINFOHEADER* pBmpInforHead)   
8 ^$ h/ H9 o% _{   
& [" S' o- ]0 H8 f* U! _& a        printf("bmp info head:\n");   
( F3 a) I9 e) U$ O$ ^; n        printf("structure size:%d\n",pBmpInforHead->biSize);   
* ?7 @3 ^( Q* u. U8 o        printf("width:%d\n",pBmpInforHead->biWidth);   : }% p1 w/ h- s& F
        printf("height:%d\n",pBmpInforHead->biHeight);   
# P! n' c6 X) H1 ?' U5 ?; F# O; M9 k; \        printf("biPlanes:%d\n",pBmpInforHead->biPlanes);   
6 }* c; \2 M6 r        printf("biBitCount:%d\n",pBmpInforHead->biBitCount);   " n9 [, k! y! P4 H- H
        printf("compress type:%d\n",pBmpInforHead->biCompression);   / x2 X+ @9 B/ w$ ]0 u+ g
        printf("biSizeImage:%d\n",pBmpInforHead->biSizeImage);   
1 q6 A6 L3 E4 Y        printf("X:%d\n",pBmpInforHead->biXPelsPerMeter);   2 R# t2 _( }  H- [5 s
        printf("Y:%d\n",pBmpInforHead->biYPelsPerMeter);   
$ Z: o( I; t/ I; v        printf("colour used:%d\n",pBmpInforHead->biClrUsed);   
8 W; \2 S* C0 S+ m) Q$ `9 ]+ a        printf("imp colour:%d\n",pBmpInforHead->biClrImportant);   
# V3 r" g1 }3 m- ^# }, f8 A}   
$ d6 h" W5 v2 N, ]. k  
' Q+ w8 [1 C% J7 r) d9 F% u' lvoid showRgbQuan(RGBQUAD* pRGB)   3 b+ F9 w( ~- q; q3 I
{    ) {; y$ s7 B" K
        printf("(%-3d,%-3d,%-3d)   ",pRGB->rgbRed,pRGB->rgbGreen,pRGB->rgbBlue);   " ~! ?3 g. u+ E* U% r# S. I
}   
6 S" T5 X. W6 w. H9 f* J  % ~! b7 |6 F8 ~# P$ i) k0 m
void sobelEdge(BYTE* pColorData, int width,BYTE* lineone,BYTE* linetwo,BYTE* linethree);
; L& `; a$ t. {9 k - Z8 p8 [  E9 }) o8 U$ R
int main()   * i8 U4 `2 v' o. Z: B
{   : ?, `  K' ~0 g7 p! y3 g3 D9 M6 W
  timeval tpstart, tpend;
, k% N' e' ^9 _7 p7 H  double timeuse;$ z9 L; t# ?) |1 d
  
1 p) t: F* x6 @( T( d0 W0 M) ^' E        BITMAPFILEHEADER   bitHead;   
# o7 Z) j4 H3 d& N& i# X6 N- J: P        BITMAPINFOHEADER bitInfoHead;    9 |, ]7 `* _) A3 t; T
        FILE* pfile;   
8 `# {0 U, p% r3 r        WORD fileType;
* R% x/ {" ]9 f' s/ r, B. S         . {  t. D* B. j' `8 u7 c: R, g
gettimeofday(&tpstart,NULL);
* `3 S3 C$ |0 ?( ]6 A/ H 7 e7 D! E5 i3 k  x2 e2 M( [2 x
        pfile = fopen("./aa.bmp","rb");//打开文件 6 P; ~6 r. o" x$ ~
        if(pfile!=NULL)   
% [$ l8 v7 z8 X6 d' A2 {        {   " q) w5 Q5 A6 W/ h4 t, P7 [. t
                printf("file bkwood.bmp open success.\n");   
2 d7 T4 e0 {6 d$ e                //读取位图文件头信息   ) T, X: q) y+ Y7 D0 W8 N9 n! k
                fread(&fileType,1,sizeof(WORD),pfile);   
- u7 ~) k+ s+ J1 p                if(fileType != 0x424d/* 0x4d42*/)   
) O" W4 e/ a7 a7 c% s' z* T0 M2 D% ]' F                {   
2 ^8 [6 r1 d3 N                        printf("file is not a bmp file!");   7 N9 y! o% [2 m7 N* K! e" M7 d' a. X  w
                        //return 0;   9 K1 i% m' C5 b5 n4 s  a
                }   
% q5 A4 S, R9 C3 {% l9 j5 S                0 O( |, n0 _/ I' ~: G
                fread(&bitHead,1,sizeof(BITMAPFILEHEADER),pfile);     U1 y" [7 A% _; i3 t0 S3 t
     
# X7 x" B: w( T/ f: M* y                showBmpHead(&bitHead);   
, [9 K/ B, K- ?                printf("\n\n");   
0 ]4 @' h' ^2 I. [# M! U  L" ~* s  
+ Q/ y. p) T+ z4 A1 }- d  C% \$ Y. D                //读取位图信息头信息   , D  L" g% w# z! M0 X/ n0 d
                fread(&bitInfoHead,1,sizeof(BITMAPINFOHEADER),pfile);   - B. y) [) ?8 F( g  J  D3 j  [! g
                showBmpInforHead(&bitInfoHead);   
, G! R9 Z9 _3 L: @, r/ y                printf("\n");   
$ |- d" d8 K) L, I8 O        }   
  K" d. E# A6 i& L( O        else  
: A3 [: k4 L$ c( F        {   
, c" G% c- Z, R: ?: t7 l! s                printf("file open fail!\n");  
2 P2 b( H' J: l  N* g: {8 {) `5 c 3 S3 k1 p  X. P" _) v( J
                return 0;   
5 O% t' @& y2 j- v1 r! ]( y) L9 d        }
& `1 j' i$ _4 g 7 B- J/ u: O7 U3 V) a: E2 @
! U" U5 d! L" [  r4 Y/ @2 f8 N
        if((bitInfoHead.biBitCount!=0x800) && (bitInfoHead.biBitCount!=0x8))
7 J2 i6 h1 v. F. `# }8 b; G( u+ O        {+ k- b6 ?( G1 S- d2 g" V6 s& O, }
                printf("not 256 colour bmp error!");6 e9 Q( A, C5 q$ p
        //        return 0;4 a) y# q- a, [& a6 N( n
        }
& C) c( j' B* t$ [1 D        " o  s. r  e1 v$ z; w+ M
        FILE *pwrite=NULL;//写sobel之后的图像
( f$ E5 m5 Y0 ]: p/ [1 c: b        pwrite=fopen("Sobel.bmp","wb");
/ Q* I5 H: x& ^9 Z, h; Z. R( p        if(pwrite==NULL)" w2 h) y) ~% w& f
        {
/ x0 q2 v* B- P6 s& W! S                printf("new file fail!");) f( e, Z: }% b2 H
        }: L! u% F( `3 B& j- \- r6 U
        fwrite(&fileType,sizeof(WORD),1,pwrite);
' r# G7 t4 R- K        fwrite(&bitHead,sizeof(BITMAPFILEHEADER),1,pwrite);; q( N* b# f: |: C
        fwrite(&bitInfoHead,sizeof(BITMAPINFOHEADER),1,pwrite);3 }/ k2 n  a6 z. |

. r: N* r& H: L' l' f8 j( I' Q   z, f5 P- W% o/ q
//读取调色盘结信息
& y; K" S- N0 l& T: c
0 }; D  C2 B; S! |6 B- h! H        RGBQUAD *pRgb ; 4 W% @' L& P& y. X+ Z; I8 b7 W
        int i;  q' d3 b- `2 t$ d
        int rgb2gray; 1 U0 g- S' y+ O& |  P! B4 D
        long nPlantNum = (long)pow(2,(double)8/*bitInfoHead.biBitCount*/);//   Mix color Plant Number;
" i# V) W3 ^" W' A  x) Z        : s4 U( H: b7 r
        pRgb=(RGBQUAD *)malloc(sizeof(RGBQUAD));
7 J, v4 u' D/ w! ]7 P8 k; P& F        for(i=0;i<=nPlantNum;i++)- z2 U: N9 O% Z' F5 R/ k: d  L, R
        {
& |6 z6 @, K6 y                  
- a! z- B- [* W2 G: f                memset(pRgb,0,sizeof(RGBQUAD));   # V' C, b" s" G" H. N
                int num = fread(pRgb,4,1,pfile);          & n& G3 S7 L4 z. W2 T3 n4 M
                rgb2gray=(300* pRgb->rgbRed+590*pRgb->rgbGreen+110*pRgb->rgbBlue)/1000;
1 @' f$ L0 j/ Z: k( t                pRgb->rgbRed=rgb2gray;+ n. b- K( P: O1 @. i# [
                pRgb->rgbGreen=rgb2gray;
; U/ s5 h' @4 m4 [                pRgb->rgbBlue=rgb2gray;               
5 x4 R6 S; c" Y1 {                fwrite(pRgb,4,1,pwrite);               
# h6 ^3 D% C% n) I        }
6 ~. e& G- M. {" d
  f+ a* w! |0 H. c8 Y( M        int width = 1024;//bitInfoHead.biWidth;   ( A1 q5 t. l6 h
        int height = 768;//bitInfoHead.biHeight;
9 M+ b7 a+ n% H, ?: w: r  R , X7 |4 c# j1 V) a. c; o4 n' k" g+ I
& N3 K! H- J4 C* v

* W0 P5 Y5 r  b; ^# h  g' y        BYTE    *pColorData=(BYTE *)malloc(width); //ad
. ^; W7 e& E$ F+ u0 Q        memset(pColorData,0,width);//ad
7 D& A  X; J6 ^ 6 K1 \/ L; w' u, S# `( q
        BYTE lineone[1024];
9 I# U) U8 I: p' y% }9 y" S        BYTE linetwo[1024];
# v' M2 H# T- y) y+ D4 ?        BYTE linethree[1024];
6 y3 L; X# z1 |. W$ U( b- m. V 8 C8 v' `) @; w: s
        int num=0;% @1 {! L) }; f' k( q
        int j=0;! l( c+ A) J# x+ ~! p
        for(num=0;num<height;num++)
& V; ]) e7 K- ]8 m7 T/ @8 a        {
; Q9 ]* _9 `# C                fread(pColorData,1,width,pfile);' l( }' V$ E' j
                if(num==0)& w3 N7 m: G8 a/ f
                        {' C7 W2 \0 r, ?! S6 b2 x/ ^
                                for(j=0;j<width;j++)
; D. i6 O8 b- Q  Z/ X& V1 H5 U+ a: d                                {
2 ^, h$ ]& d6 }4 r4 a2 m) P                                        linethree[j]=pColorData[j];                        2 ]* U/ K& r' g+ `/ j
                                        pColorData[j]=0;
+ T/ ~& b" D+ c                                }  X* r  w+ m9 o) L8 G
                                        fwrite(pColorData,1,width,pwrite);
4 }) u" r1 \$ v! N2 f8 ]                        }7 L7 X5 R: K& f; ~
                if(num==1)
+ `5 L: v: @- M0 e7 h# ?9 [                        {
  K+ f$ g* e( n! }) {                                for(j=0;j<width;j++)
/ P$ ~! \7 q+ l                                {
5 j; J& l8 T9 b$ X: K                                linetwo[j]=linethree[j];
9 A9 {3 {) Z. c8 z. L$ H                                linethree[j]=pColorData[j];                                
" w' |" ]8 h6 q$ y( v. f9 I$ A                                }0 P' E) z4 }0 b7 A2 c* A" J1 u
                        }                + g1 v7 t7 X  A( B3 C' P
                if(num==height-1)7 R% s2 P# i9 K  h$ z7 \. B. u& ^5 {" h
                        for(j=0;j<width;j++)% J8 g9 [% S0 s
                                {                                                                2 K- c- f& U) @( `, O) {
                                        pColorData[j]=0;
" a4 b, u& g8 \                                        fwrite(pColorData,1,width,pwrite);
& w: p$ J# V6 U3 m" L+ D                                }                        
5 R7 p( a  E# |# }  ^# ^3 l                else* n. t) s8 k  f8 Q
                        {                        
2 z) A; y. s0 P- }1 v- {                                for(j=0;j<width;j++)
, H; B3 d! o" @# e. ^3 a                                {; F4 {5 R, L' T. _5 [
                                        lineone[j]=linetwo[j];
! ^; I2 R5 i0 j! Y0 |3 u. e; P                                        linetwo[j]=linethree[j];
6 \& {/ W2 F; i                                        linethree[j]=pColorData[j];/ e( U: h! T4 M+ @
                                }. \3 K! r% m: a1 U: \2 H# X4 ?
                                        sobelEdge(pColorData,width,lineone,linetwo,linethree);
' {  J+ M4 A% s) F7 n                                        fwrite(pColorData,1,width,pwrite);- ?. }1 H4 B- I  {& R" P
                        }        
6 E5 J$ S: g0 S% [) r        }0 X8 z/ X: G8 |( E# s9 C) J9 V& @+ O
        fclose(pwrite);
+ A: \* U7 w& ^- l- h, d* P7 V% q( Q        fclose(pfile);    ; x& Q: L1 ~( A
        if (bitInfoHead.biBitCount<24)   ) _) ^( V( ?8 ?8 K" I
        {   ) }& U: K; z  p3 U. i( b" r0 G
                free(pRgb);     }+ z( m% n' j. A" \4 H) I
        }           
, A5 ^1 M7 P- v* T        free(pColorData); + J5 F' V* W( d. x
          : S/ W# h( ~# f
        gettimeofday(&tpend,NULL); # Z) e4 B% B# p: c
        timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+tpend.tv_usec-tpstart.tv_usec;7 W; O/ S# g* ?% z1 `' h. R' F# a$ m
    printf("sobel_soft Used Time us:%lf\n",timeuse);  
$ P1 T; S( H7 P  H1 y        return 1;
7 g: e2 M2 s- ?, q! x# i: ]}
0 ]' s# E# `" bvoid sobelEdge(BYTE* pColorData, int width,BYTE* lineone,BYTE* linetwo,BYTE* linethree)
5 c5 {+ f8 v) u4 H{. `/ J, ~, [, F( z/ ~6 N
        BYTE area[3][1024];
: ]1 ]8 p- V1 N3 ?9 a; {        int i=0;1 k/ |/ d0 V; n# O9 l0 l$ w8 o* J
        int j=0;
" j. Y% W2 o0 C1 l        for(i=0;i<3;i++)6 _8 X' E# j# m/ G
                for(j=0;j<width;j++)! n" a" x  m! n8 J0 i7 i
                {# n, ?- j, M8 W# G( Q5 d
                        if(i==0)
3 m) P8 v3 A6 d5 N( Q- m1 t3 w                                area[j]=lineone[j];+ ]1 `- ~) e9 V( l
                        if(i==1)
( U- S- o/ e$ J! I" i                                area[j]=linetwo[j];
# S4 @# M  G! a; y) M6 ~                        if(i==2)
9 a4 j$ {- {, K2 I; u2 R( y                                area[j]=linethree[j];
1 z9 M$ I8 H7 Z; Y                }
& o1 @$ z9 Y" J5 ^; \4 {        int temp1=0;2 Z, E  n6 |$ Z. _4 l+ a. w: q! W4 {
        int        temp2=0;
% e1 }! F7 A' \3 @4 J        int        temp=0;; }# M* p. }( P7 U- q" i9 @3 L& y
        int *tempM=(int *)malloc(3*width*sizeof(int));
9 r1 D2 I6 L' ^2 f; @4 q5 x        memset(tempM,0,3*width);
  s* u6 G; c7 d$ D- y$ n; f        : K6 E, H5 h  b- O+ T+ |
        
' @4 k9 r0 U; W- A* i5 g        int m=0;
; l  N5 o  i7 B* T        int n=0;) }! t4 Q3 e+ V0 j. b
        for(m=0;m<2;m++)
; _/ f+ {; G0 [* E: S$ J. b2 p                for(n=0;n<width;n++)( V2 c, |- H/ E! X1 v) j
                {
+ E9 M) v" ~/ V5 x2 Z                        if((m==1)&&(n!=width-1)&&(n!=0))
+ ~. z! _% O! S0 r                        {; v, D4 k6 {/ Z  ]5 q" S% j
                                temp1=area[m+1][n-1]
2 W" o4 H! L3 e/ X! n                                                                +2*area[m+1][n]5 Z/ H* {; u4 b4 @# [
                                                                +area[m+1][n+1]# A. x% c, m% `9 @6 C9 I2 y
                                                                -area[m-1][n-1]
" j* w; b) P% K- A                                                                -2*area[m-1][n]/ \3 J5 f3 S% B' b/ Z9 M; p
                                                                -area[m-1][n+1];
1 |8 [9 o9 T  S) k0 f9 y. `                                temp2=area[m-1][n+1]6 H7 U/ I& D% @
                                                                +2*area[m][n+1]
7 Y, C. O% m4 w7 g% }8 j, {1 i                                                                +area[m+1][n+1]+ v9 E8 n) L/ ?( x# L! @& O
                                                                -area[m-1][n-1]4 Z7 t. ], @9 O3 v' y
                                                                -2*area[m][n-1]
" a6 n9 T" K2 ?# t                                                                -area[m+1][n-1];
$ {. T, [& u6 O                        //        temp=(int)((double)sqrt((double)(temp1*temp1))+(double)sqrt((double)(temp2*temp2)));& z; S# j, M8 b( Q- c
                                temp = (int)(abs(temp1) + abs(temp2));" n! p( U5 `- r; [3 K
                                if(temp>255)
. U8 M6 h& Q; S) s4 d: M* m                                {
: u0 _+ q! N4 |+ L0 e                                        temp=255;1 b* r  K- D! N! U$ m) k1 i) m; z
                                }" |0 P: w: Q. r# r/ w
                                if(temp<0)+ E% J) m* V# c( C0 Y( I3 @& }1 h
                                {
; s$ i, M$ m* T& A, J                                        temp=0;
' \* C. O! \( A$ j0 P  p0 N                                }                        
- D5 Z, p; Y/ Y# D6 a                                tempM[m*width+n]=(BYTE)temp;' F( G4 \5 Z3 H0 A) W% A
                        }
9 k1 `8 i3 V; q7 H+ U4 ]1 O; L                        else: @: k/ G9 X0 Q- n9 c$ o- p+ l
                        {
7 c* \% e; r; f8 r                                area[m][n]=0;! _/ j; h$ \" D* s/ v& o0 Z' _4 i9 Q! Q
                                temp=area[m][n];, L$ M# w. _2 q8 i# Y
                        }! V6 b; F: S9 {8 r8 J
                        : A4 q# ?7 @# p9 r/ |
                }0 L# G9 ^8 R" y+ z
        for(n=0; n<width; n++)& r+ v; C1 v4 m
        {( f! ?* A: x9 x8 Q* ?3 V, r
                pColorData[n]=tempM[1*width+n];
: q! y: U0 q" H. n% j, g( O        }+ M4 Y* E. |: |( L9 G5 p
        free(tempM);
8 F" H9 x1 Z$ ^: Q        return;
9 W3 |; a, F1 n6 _3 P}0 l- ?3 N/ ~# i1 v2 o! i0 B* o- s

1 k/ u% R; P, z) q1 m; v1 P9 `! j& a' g- M5 S2 P4 K: B
, m8 p6 Z# `. u( [  F

2 F5 D5 _9 @. _& f/ ~在虚拟机下编译:or32-linux-gcc bmp.c -o sobel
" z. e. h) }: b/ C4 S$ \7 z+ p
$ t0 ]3 U# ^; Q- O' W& I7 e  X4 Qcopy到开发板上执行,得到打印结果如下:从中可以看出,软件执行时间为17972.718ms。时间对比=762.76倍。硬件加速效果明显。当然,实际情况比较复杂,不可能会达到这么多。9 I  a8 h7 G) y6 w$ j- P' W6 C1 Q
3 d) K: q( x. Q5 |( h% q8 P

3 U1 R3 x+ q# Q+ P6 Z# k1 T
5 L$ B9 h' r) x! L: ^
4 y1 Q& w3 M; v3 p( }6 S: K1 Z! u! C% Q* v
软件处理结果:与硬件处理结果有所差别,原因是处理算法和预处理有所区别,但区别不大。2 G- `7 J, G8 F# C8 a- z5 |
7 @5 O* i' r3 Y0 L; e- {) |5 R
  i4 T& H3 W4 r: }

% T! R, x' G: `. g- f
$ D% t7 n8 r; h3 q& B- z4 h. M# N( L' v- a7 @; O
6,小结
" p1 v( N( i" l" L, b3 X, ?0 P! f本小节设计实现了一个简单的sobel减速器,并编写了相应的软件,与之对比,加速效果明显。6 `" W2 _! f. L" D

( P( l( L+ s$ `/ g5 r* n$ S" H/ d, k! N4 m: F

/ @5 K' A4 U/ C- z0 M: {; h( `' ~8 U! L

0 m- \1 p- P6 m2 p7 ?+ B6 \

该用户从未签到

2#
发表于 2020-5-28 13:13 | 只看该作者
简单sobel图像边缘检测加速器的设计,实现,仿真与综合
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-11-25 21:36 , Processed in 0.265625 second(s), 27 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表