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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
. @. w# q% ?! ^) y2 y
引言
! w2 r6 q! s$ d/ M图像视频处理等多媒体领域是FPGA应用的最主要的方面之一,边缘检测是图像处理和计算机视觉中的基本问题,所以也是最常用的,随着数据量的不断增加以及对实时性的要求,一般软件已经不能满足实际需要,这时,就需要专门的硬件来实现加速。本小节就实现一个简单的sobel边缘检测加速器,为了便于对比,我们还编写对应的软件算法。
( n1 F& ^0 Q% h% L& U) j0 W, B" K8 L4 D5 V6 g- R
' N( R/ Z: F& D- ~! v
6 j& |" ^9 X$ w% }
1,基本思想与算法
- d7 f4 p# Q/ t2 i3 [* |( I1 e* o# GSobel检测法通过一个叫做卷积的过程来估计每个像素点每个方向上的导数值。把中心像素点和离它最近的八个像素点每个乘以一个系数后相加。该系数通常用一个 的卷积表(convolution mask)来表示。分别用于计算x和y方向导数值的Sobel卷积表 Gx和 Gy 如下图所示。+ c4 k# }% ^  e' F% }" r& g8 [
4 M! @. w1 j2 A- b% |! t6 l
Gx:
& ?! P/ q( `, c! @# e. j2 F% V; e4 R1 S  A0 z) s
Gy:0 A1 Q/ l4 L* G0 f
) P/ G/ g  D7 |4 |+ {5 _  Y
( {( p& h/ ^" z
我们把每个像素值分别乘以卷积表中对应的系数,再把相乘得到的九个数相加就得到了x方向和y方向的偏导数值 Dx和 Dy。然后,利用这两个偏导数值计算中心像素
" j. g- k9 R+ c4 J: S! v# k1 e: ]3 n& Y点的导数。计算公式如下:  T$ m+ `) h' U$ ~" {) S2 p
/ A. B( D. {7 U; @3 Z

( {7 [; M* {; W
' U+ H# D) ~9 Y$ D由于我们只想找到导数幅值的最大值和最小值,对上式作如下简化:# c) P; E" k+ H( y( a6 e
& U5 `3 s$ g/ x2 e  d
, C: y5 b1 v. o
  M9 z, P) @. Z. h% x8 Y
这样近似能够满足计算要求,因为开平方和平方函数都是单调的,实际计算幅度的最大值、最小值与近似以后计算的最大值、最小值发生在图像的同一个地方。并且,与计算平方和开平方相比,计算绝对值所用的硬件资源少得多。
4 _* h( m7 o) d0 _4 x4 K
$ c: [3 x! g- B$ r2 _; u; M1 ?% D我们需要重复地计算图像中每个像素位置的导数幅值。但是,注意到环绕图像边缘的像素点并没有一个完整的相邻像素组来计算偏导数和导数,所以我们需要对这些像素进行单独处理。最简单的方法就是把图像中边缘像素点的导数值值 |D|设置为0。这可以通过软件来完成。
) f2 X, E2 F! x* K: ?/ w5 Z8 [
; D% S, j; s' w8 z- A& n/ ~) e, q我们用伪代码来表示该算法。令O[row][col] 表示原始图像的像素点,D[row][col]表示导数图像的像素点,row的范围从0到hight,col的范围从0到width。同时令Gx[j] 和 Gy[j] 表示卷积表,其中i 和 j 的范围从 -1 到 1.
( Y* f- M- `3 j2 k2 o, J2 C$ A; G# o7 n

! S3 D/ d4 J+ E( z; v6 ~0 m
) R" M  J/ j- ~/ H- o/ xfor( row=1; row<=hight; row=row+1 )
: i9 M& S3 Z) o- j {! m8 r" w7 e' J5 \2 l' m# {( v5 o# V
       for(col=1; col<=width; col=col+1). A2 x% ~. E) w6 r1 N% F/ N8 Q
        {
3 h4 z7 [9 i/ d0 D% ~4 g  ]                  sumx=0;        sumy=0;
  X. U: [! e. E  k# T: U9 f                for( i = -1; i <= +1; i = i+1)   / s* ]3 _4 E4 S% Q) ]4 ?
                {                                
4 M3 a4 c  O+ N. g& S7 b                        for (j = -1; j<= +1; j = j+1)  * J$ K" s9 Q8 q
                        {                        
( {, T5 _' y/ J  h% r3 ^                                sumx = sumx + O[row+i][col+j] * Gx[j];- A+ v7 n8 r' m, j& x" f0 t2 @& F
                                sumy = sumy + O[row+i][col+j] * Gx[j];9 K& A" @6 K  A; P/ M* p8 n5 ]
                         }
8 R" {0 x  O( c: h                     }
3 M( r' V& B- d' a; P3 R. j                        D[row][col] = abs(sumx) + abs(sumy)' j) y: W* N0 Y7 b
        }& w- y7 l# j5 x0 q& d5 Q
}
. ^6 O: ^* k. e1 H/ b$ t) N7 |
  `/ b/ w: Z+ x9 H3 @/ D# F  y) \0 H5 k/ {2 E" G8 W4 m

# U& J/ N3 S! _& C- w; z- j" A# ^. D2 `9 @  @
$ G: ?- [7 ^2 _5 o' E

5 ?7 S9 b* A- p; r6 c2,硬件实现
6 o, h* c6 v; m; R  Z/ n一旦明白了sobel的实现算法,我们就可以根据算法来划分模块了,本例中将sobel分成了:addr_gen,compute,machine,sobel_salve四个不同的子模块和sobel一个顶层模块。
- \6 \5 C, w9 I' Z: H! k; I/ ]" L# |8 ~" X* m
需要说明的是,sobel加速器最终要挂载SoC的总线上,所以需要一个统一的接口总线,本例中采用wishbone总线,关于wishbone总线的内容,请参考:http://blog.csdn.net/rill_zhen/article/details/8659788
/ x4 O1 ~- M( O, `% U4 v5 W& x* v* V  y1 K. {- T+ d
此外,由于sobel加速器只加速核心的数据处理部分,但是,对于一张完整的图片(例如bmp)还有其文件头,所以bmp的文件头的数据需要事先去掉,当sobel处理完后也需要再加上文件头之后才能用图片阅读器打开。所以我们需要编写相应的软件程序。+ t  H- H+ ?4 x5 a( u
; f6 V2 F$ s2 M' F. G
下面只给出verilog代码清单:
# C- c# h% Z* m3 K# B
4 J2 x0 ^% w3 m2 K- d- e; g# s- [* H; O) Y$ O
8 Q* w% w. Y* _+ J) P
sobel.v
$ Z4 @# }1 E# w- `+ V# p' _0 G+ }: `4 Z& {

( \1 {- q2 H/ }! P) z
2 ^! P3 }' X) ~. b$ w`timescale 10ns/10ns  ~* `  a6 C9 K$ I: r
module  sobel    (
1 y  c& Z0 }4 }                 //master slave share i/f
4 j" }! s5 v  u- A3 B                 clk_i,
4 {# d: g, S; K5 K9 C( R  h0 I5 N                 rst_i,
) G0 H: \) l8 f( `7 \5 T5 T# _$ J- M                 dat_i,
- `( Y. B! F+ p9 G! G' P0 B                 dat_o,# x5 ?" `. V: _( F# N
                 //master i/f1 F1 N7 @. |, N, q
                 cyc_o,
( q7 \, Y$ r9 E. U, x: G                 stb_o,' q, L8 c' i+ I  Z' z; q
                 we_o,
) C3 p, a' {2 L9 N' v  ~/ {5 y! o                 adr_o,
0 w) h# q: T1 b' O& X                 ack_i,2 {+ @& u8 S' J' ]' w
                 //slave i/f8 \  k7 k# U2 f: @0 U4 x
                 cyc_i,
5 M- G+ ]" u+ q3 ~                 stb_i,3 d" m- H* T6 Z3 g
                 we_i,
! f. j0 r+ ]2 ?7 m8 q: i; L: ?                 adr_i,; Z- G# a1 k6 n+ G; e( E3 L
                 ack_o,6 G6 y" y2 @3 D  }% h' v; g2 L+ o
                 //debug i/f
1 @  N* }& w6 u6 n                 prev_row_load,
. |% T6 G" F0 }! \6 _: |                 curr_row_load,
% j+ L9 h5 V' I% a5 O& E                 next_row_load,
' A, K# v1 z3 ?1 Y/ {0 E                 current_state,
2 C4 R. r9 \- W% H  h                 int_req//interrupt
* K9 N  v& X' X7 O) ]* N                 );
& C# Y1 h" G. ]  m+ n                 
, T* z3 Q- V# {/ qinput  clk_i;7 A4 y% y; o' Q0 P% \. T
input  rst_i;9 {: ]% r: ^7 Z. O, L
input[31:0]   dat_i;
- E, \+ o0 Q( i& w. l5 Woutput[31:0]  dat_o;2 P; R, y9 ~$ @" D! Q
output   cyc_o;
7 F/ b9 U6 N7 z) k; q( K* Ooutput   stb_o;
. ~& W" C7 q* ioutput   we_o;! }3 n0 d2 l& z) Y
output[21:0]   adr_o;
6 j3 m" K! b" C" Linput    ack_i;
, j( r$ c$ @1 c) j0 a* `% einput    cyc_i;3 h( F) G" J( m5 Q
input    stb_i;
4 C9 d- \. |' @. h* p' ~input    we_i;
  a# A, R8 o( s+ p1 O. Zinput[21:0]    adr_i;
) H7 J) _1 \4 m/ N( |output   ack_o;
0 f- K8 e: ~; H/ U4 C- r3 O) poutput   prev_row_load;
* _6 g3 ]6 ^# f: ]output   curr_row_load;
" M- y8 l2 D7 ^  routput   next_row_load;
% u4 `6 {! l. X* m; ~1 P* N; uoutput[4:0]   current_state;
8 Z% y5 H: T1 n3 routput   int_req;( E* E$ U: l0 O) N! v

  ]0 R/ t' Q" H: |9 d. Jwire   start;# W0 o0 Y+ q$ G2 O/ Z
wire   ack_i;
+ X/ ^/ D: K$ |( Fwire   cyc_o;0 K6 I1 [4 B" q5 f1 ~
wire   stb_o;
3 |9 q, V" R% ?wire   we_o;
" [! M- z  ^) c9 n# Q! Zwire   O_base_ce;. B( Z! R5 ^+ u; v9 V* w
wire   D_base_ce;; @/ ~* l' F1 x' Z& n) g7 v
wire   done_set;6 m# C1 J( ]* }1 @) \4 z/ O* U4 w, P. ]
wire   shift_en;, j4 i$ L! L3 t  s; Q! F
wire   prev_row_load;* t. B7 V6 |! R4 X' t: d! O
wire   curr_row_load;
% `8 T3 w8 z; ]* F& cwire   next_row_load;
3 ]3 a' G& j' l" |wire   O_offset_cnt_en;% p  b/ K" x! W  l* w. l
wire   D_offset_cnt_en;, v" c$ N; p& Z" P" v5 y2 N
wire   offset_reset;
$ C/ E* ?+ ^, v' h$ @2 Owire[31:0]   result_row;
$ D5 U  `( |, xwire[31:0]   dat_i;
5 @  Y' s+ \3 lwire[21:0]   adr_o;! \7 V* B7 _; C, C: t+ S
wire ack_o;# w, j) r6 t; `8 T: r( V: ~* c7 y
wire[31:0]  dat_o ;               
1 {* q! a  [# {! P3 n# T! S
8 x0 o/ B3 D6 }1 Iwire[4:0]  current_state;
* ^& w; h: x3 e. P. p 3 V7 `- `- P4 t! l5 H
//module sentence
0 b) d# n2 s# O+ S4 r$ X + i. O4 R7 V! B2 c- a
compute compute(
( F" Z$ F8 L6 I                .rst_i(rst_i),
( g/ T7 v& t  t% S" Q                .clk_i(clk_i),
, M' x" J: p. V4 y' I% u3 \                .dat_i(dat_i),
' p4 G% D8 m6 X0 }  Q& Z                .shift_en(shift_en),0 R8 u) |% e( [% j9 \
                .prev_row_load(prev_row_load),
% k( w0 i; I( f- ^                .curr_row_load(curr_row_load),
& g9 z% e. u, R                .next_row_load(next_row_load),
% U2 Z8 O! p2 l0 ?0 g8 x" n% z                .result_row(result_row)
3 c* f( E" z/ H. O& e                );
  e- c3 h$ X6 G. T" m+ u
. e9 K$ ^  K# Paddr_gen addr_gen(: d2 x1 N! j  }
                .clk_i(clk_i),
& P# ~, w& a# d% j, E; b; c                .dat_i(dat_i),& p8 I" ~' l2 E- `$ o( K+ P
                .O_base_ce(O_base_ce),
4 K; M, Q$ d, H                .D_base_ce(D_base_ce),0 c" Q9 a8 v8 U  l0 P% v
                .O_offset_cnt_en(O_offset_cnt_en),
% l1 Z& a& Q& ?4 r                .D_offset_cnt_en(D_offset_cnt_en),
  T7 w" I/ \! a+ n                .offset_reset(offset_reset),' ^) l( S# S& c
                .prev_row_load(prev_row_load),
1 g, w/ z0 j" H2 Q6 X0 C$ M8 \                .curr_row_load(curr_row_load),7 o5 {5 T& d" T! h6 ?
                .next_row_load(next_row_load),
, X! G1 k/ `; p$ k: L2 R                .adr_o(adr_o), u; ^4 i. _; L# H9 r
                );+ e4 e2 y6 w8 o! Q, x
machine machine(
" O/ ^( p4 F! B6 A5 x2 y               .clk_i(clk_i),
: E3 A  ]* _# k7 R               .rst_i(rst_i),/ y2 x3 ^# W, Z# l
               .ack_i(ack_i),' X  [6 Z; ]2 e; Y. C6 ]
               .start(start),
$ X5 S+ P: b' P4 p               .offset_reset(offset_reset),1 @1 _% l8 q" @- P3 ?
               .O_offset_cnt_en(O_offset_cnt_en),
, y- A" O4 f% G( o" C5 u1 {) a# ?               .D_offset_cnt_en(D_offset_cnt_en),' S1 `2 P! X) c% G# e( p/ w$ K+ e
               .prev_row_load(prev_row_load),
+ i; L  ~$ [) B) c               .curr_row_load(curr_row_load),
! J$ N& W( U6 s0 S2 h5 _7 j2 \               .next_row_load(next_row_load),7 G; n  x! D! [0 Z9 ^2 X
               .shift_en(shift_en),/ S* f8 ]: v2 w4 |
               .cyc_o(cyc_o),. w" F. q$ E6 C* c( ~8 H/ U# p- _
               .we_o(we_o),$ N5 w: `6 l! Q, m+ D; [
               .stb_o(stb_o),, m' m4 ]+ w/ d3 F( z) g
               .current_state(current_state),
( l( |( t' g) U0 e               .done_set(done_set)
/ |, u( Y' Z. J               );
( K! \/ Q" H3 P! W2 M+ Z: vsobel_slave sobel_slave(
* y. @4 O+ _" n# D( A  J                 .clk_i(clk_i),5 k) R& f+ C; o+ w
                 .rst_i(rst_i),- L8 w2 C! w5 a; \% P- f0 r1 E2 Z
                 .dat_i(dat_i),  a1 _: A6 @0 b; m) Z1 k
                 .dat_o(dat_o),                 
! ^  L$ f, f3 C% a                 .cyc_i(cyc_i),& J+ E3 Z0 O8 I% ]9 {# M+ b  w. r
                 .stb_i(stb_i),
: X4 N# ^; ?" L* p                 .we_i(we_i),3 ?* ^: i1 R4 ?% [, H
                 .adr_i(adr_i),
! o3 y7 L/ U, a1 m. E                 .ack_o(ack_o),
4 n4 m4 }* [2 t; {                 .start(start),
: `1 R3 x' x4 I" x& \9 a+ k6 g                 .O_base_ce(O_base_ce),
, ^% r& j9 y3 `+ M  M                 .D_base_ce(D_base_ce),
# k3 m2 o. V9 H. w# t- b                 .int_req(int_req),
& m3 F% e8 |; R0 d+ }" b                 .done_set(done_set),
. k$ I" T, y& i7 g. ~6 q                 .result_row(result_row)
7 D- f7 G% {8 i' x% }                 );               9 t, L; P6 U# C# m- b8 x/ U
endmodule" {% e" y/ u0 K7 }  e4 P
( g# M; N/ H+ ?* g1 @/ i0 U
addr_gen.v8 g  S( C  P6 q
7 e" K( M/ C3 @$ {
9 M6 P# A. N% \" a3 t2 Z! c. n
`timescale 10ns/10ns/ p+ M1 _' @1 R* Q
module addr_gen(9 _: Y! J% v- M
                //input
( V' u2 ~1 o2 Q- l' X9 J; k                clk_i,
' d( d+ T( k+ R                dat_i,( [0 L* w' U+ F2 U, X5 i
                O_base_ce,
4 J9 I1 j2 S' h7 D1 q6 l' I; I                D_base_ce,9 z6 I/ d, [% W% X4 G% r. k
                O_offset_cnt_en,
  x! s( [( [5 ~* f                D_offset_cnt_en,
  t8 ?2 w" T- ~3 t, o9 `                offset_reset,- ^/ d% J. E; w# [$ M- i0 s- c
                prev_row_load,3 U/ n. X' A0 G4 C" B
                curr_row_load,8 Z7 ~# k3 ?3 M, ^, a& \
                next_row_load,
, ~" [& N+ n% k* ]* ?5 W- ?6 N                //output
  j/ S1 B4 M* ?0 A& \                adr_o$ J/ ]: i, N' H7 t$ j' i
                );8 h8 w" U" W  z2 @7 W* Y4 P# X) C
                                + v- o1 {6 A) o1 n# Y& L( t& h. u
input clk_i;
1 t& V2 R- b  [$ dinput[31:0]   dat_i;
. A+ Z+ B! l4 e( q& O$ }, ninput   O_base_ce;- v- w4 w& _/ ~
input   D_base_ce;
$ n9 N( o! c4 S8 f) T+ `input   O_offset_cnt_en;
( L/ [( a& g/ n. K; ~input   D_offset_cnt_en;              4 }3 A6 W" K9 j0 l7 h/ v
input   offset_reset ; . {, o  B% A: U8 l- S$ H
input   prev_row_load;        
) I% c6 `8 B, u! Qinput   curr_row_load;      - f+ o% J# q+ M
input   next_row_load;
2 U) d4 j6 ^4 r. r
$ _, N8 j) J& [/ E6 eoutput[21:0]  adr_o ;       4 t- j( i' ^  Z8 n, [' c# K" t
9 M3 Y5 r$ x( V( |  r) g- s
parameter WIDTH = 1024;6 t5 a8 V( K$ l% G" d$ V

* P7 ?5 a1 _3 ?% W6 Q9 creg[19:0]  O_base ;
: A# t4 B, \# T% X' B: Nreg[19:0]  D_base ;               
* I4 `4 a% R# b# K) \$ o: greg[18:0]  O_offset;
6 m& Y1 h* I6 ~- b, }# Ereg[18:0]  D_offset;5 Z% T% b3 z% p7 q" h5 v' d
wire[19:0]  O_prev_addr;
% F# m  p/ j, q0 _- j4 I1 Ywire[19:0]  O_curr_addr;2 ~$ e! m7 g% T! v0 Q
wire[19:0]  O_next_addr;         
3 n; A% Q$ Q; U5 V9 J8 \8 {wire[19:0]  D_addr;
+ V7 C4 t9 d. M1 ~ 2 N+ [- Q6 g, i( \2 r- f6 C+ G% T
/*******************************************************/# ~( \4 i' a! E
) D; L! W/ Z6 A% W- C, a( e3 {# h9 J
always        @(posedge        clk_i) //original data offset: r8 D- Z2 O) u7 B- _
        if(O_base_ce)        
" q8 ?4 K: e1 y& |2 x          O_base        <= dat_i[21:2];
6 n  a3 y3 ?- h1 Y3 @8 a: Calways        @(posedge        clk_i)        //original data offset cnt' l7 B( G$ f0 r/ v- L
        if(offset_reset)                9 l7 @/ l/ |, v3 B/ t5 U" d+ ]
                O_offset        <= 0;  p* x. G3 Z8 l& a: {  D
        else        
2 H! a) j: t. F0 M# D          if(O_offset_cnt_en)        $ r+ s  k5 P6 k, j4 H$ \
                  O_offset        <= O_offset+1;1 s9 [% M0 e6 _" K& x- r- L) y
               
2 E0 h' W' U6 G: j. d/*******************************************************/
/ U: i) Y, }2 |: massign         O_prev_addr = O_base + O_offset;6 T( u/ _0 _) ]" J; Q9 w
assign         O_curr_addr = O_prev_addr + WIDTH/4;
, Y- h. B7 C" P' y; _  b5 dassign         O_next_addr = O_prev_addr + 2*WIDTH/4;
: b) L0 Y& \. K9 u/*******************************************************/. d3 P! |, B3 @5 D' q9 H" N. o/ B" I
always        @(posedge        clk_i)        //destination data offset* f7 u6 I5 X. O/ L$ P1 m1 e9 e
        if(D_base_ce)
: x* i/ y' c6 ?/ J7 j  A                D_base        <=dat_i[21:2];
4 s  r6 t/ I& W: Ralways        @(posedge        clk_i)        //destination data offset cnt
. Y6 i' `  U4 x; U0 H- [        if(offset_reset)               
, k4 }1 G% E5 F; ?, t                D_offset        <= 0;
9 K! Q6 y  Z+ f        else        
, k- j$ `2 q- q          if(D_offset_cnt_en)        
. x; f/ r. J- r& D: i1 D4 w             D_offset        <= D_offset+1;$ L' @2 {+ {9 }
                 
3 X3 ?" d: n) e2 h' w8 |2 j/*******************************************************/, f# z5 J& O( }* o6 U8 B/ a
assign D_addr = D_base +D_offset;" E5 Q8 A5 h0 y7 {- @
/*******************************************************/! s, S5 X/ q$ N  J" @+ s/ A0 @
assign        adr_o[21:2] =    prev_row_load ? O_prev_addr :( F. d% r1 y2 i& K7 K3 ?
                                                 curr_row_load ? O_curr_addr :/ m9 v5 |5 k7 p
                                                 next_row_load ? O_next_addr :
" l4 W# o6 F' r* I                                                 D_addr;+ S7 f* c4 V- T( f; u: i3 d
                                                 7 Q, M+ D! k. i1 y3 s  `+ L
assign adr_o[1:0]        =        2'b00;3 q" Y3 q, L8 u/ w
endmodule
$ X( X3 z5 t# U$ `5 X7 V
9 M* j8 F) T# ?& r- T
3 r8 G- L" S, h. g( Wcompute.v
! w- A9 r1 ?, U7 M
) _+ d( X0 Q  T. J7 }  L7 |, M+ y7 ]6 F, X+ C  C. W

1 B+ ]+ |% ^! C1 X`timescale 1000ns/10ns5 M  w5 |; K, f" N  z

) }$ f- p) N/ h$ imodule compute(& c4 H9 S/ u6 y/ x
               //input) t! h+ w$ @9 l5 C( X) F5 S
               clk_i,
; q( E8 D2 P9 b" F9 V1 Y6 J/ _& Z               dat_i,4 \  V  {! a6 N2 x6 ^7 j
                           rst_i,
" k. s& x9 [. T+ s. O               shift_en,
2 m& m' P" a( I4 A1 {) S/ w               prev_row_load,- X5 G8 F/ B8 y, ?7 q. T3 a
               curr_row_load,
. X  b( \2 k9 |- B9 i               next_row_load,+ V% `2 ^- I& @2 b0 m- Q, X  U
               //output
6 @5 z' Q- U; ?- r2 i, @2 E& O               result_row% ]/ Q, X+ [/ Y, g5 L1 O; v) w
               );6 `/ S; @# @* i4 k0 Q; F" g

: Z' N, s* B- d0 @, u7 Jinput clk_i;
4 S4 L2 l/ U, `# W. ^4 d& Z! rinput rst_i;. D$ E9 _, T9 D' `. t
input[31:0]   dat_i;) J/ ]; ?/ B# Z
input  shift_en;" u. d8 A0 R% A8 M/ O
input  prev_row_load;
1 I* j4 N  h% O/ E) xinput  curr_row_load;1 n) V, D) P; z- b
input  next_row_load;
  t7 B2 r+ ]" Bwire [7:0] D1 ;, B3 V! P, N; ~4 n" W3 O  o6 `
output[31:0]  result_row  ;   6 F2 n; L7 Q, @' _: C5 q9 t
               4 w3 T, N6 i5 E6 s3 ^
' \1 l  ^% C- n, T: D+ S$ Y
reg                                [31:0] prev_row=0, curr_row=0, next_row=0;- |+ U+ T4 T/ @7 c7 T) m9 ]
reg                                [7:0]        O[-1:1][-1:1];
; e9 ]* L  R' b; z. m* p  H5 o9 X ! r! B6 k- W/ K7 b
reg signed         [10:0]        Dx=0, Dy=0;
3 n6 ]- P, N1 k1 x0 L 1 ]+ Y7 t  l8 v* s5 C, I6 D7 z3 Y
reg                                [7:0]        abs_D = 0 ;0 @4 Y8 o3 i4 L$ f5 L2 x& H
reg                                [31:0]        result_row =0 ;8 ]% M: i, V/ a) g0 i) k* A
. a5 {, A( z6 }

) H0 e2 T1 [1 ]# `( E# Y- I( Falways@(posedge clk_i)* L1 T1 D9 Y! n
        if(prev_row_load)         
+ D9 a- N% Z/ F: b* x  Y$ y           prev_row        <= dat_i;* ~! w6 M: [' \& [& U+ M1 i
        else
4 m5 M+ i( U  |6 w, m          if(shift_en)                3 r, A5 O3 ?9 a( q3 \$ Z4 O
            prev_row[31:8] <= prev_row[23:0];! c7 \/ J: ^4 A$ [
7 }+ M' g% @& x% W" c; U5 X
always@(posedge clk_i)
7 x8 [9 Z8 n3 G4 D3 |        if(curr_row_load)         
# Z# ^7 ~, X5 W$ i5 P4 E           curr_row<= dat_i;
* p* I/ _# v& x" B        else
% r$ U' w& l  q# M          if(shift_en )   
- t; L( g/ h, A/ {7 T& ]  q            curr_row [31:8]<=curr_row[23:0];
' U6 k2 B! v1 S3 Z5 U1 |/ J
, |; S7 e* B- c; salways@(posedge clk_i)
: E* g: q( V* ^# ~        if(next_row_load)         
$ X" p% R) D6 M0 ~  [. d% l           next_row<=dat_i;
& Y( Y! f# L# B( X! ~9 R1 t        else
2 P5 E6 }0 c7 L" V) @" y1 u" Y          if(shift_en )        
( N( ^6 Y3 Q% d7 h5 d( n3 W             next_row [31:8]<=next_row[23:0];7 G7 |, C( d& O1 m& X
7 L, E2 U' @" R: Z
9 U5 |/ [  h0 ~! f3 h
function [10:0]        abs ( input signed [10:0] x);2 a! C! b3 D- ^
        abs = x >=0 ? x : -x ;" x1 A% J: P( L8 `
endfunction
- j5 {% p3 r+ b5 F# o( U3 ?7 Z ; m5 V6 W1 e. t: D
//comput pipeline" |* A7 x7 ?# _+ O3 R3 Y& K

% C; ]1 _* l9 c3 n3 Y5 O" salways @(posedge clk_i) 7 u' h5 W  @$ I2 y* i5 @: N! U1 I
   if(rst_i)/ b2 g4 B5 F; x% q
      begin
4 l& G" {" R% n/ |" x7 @            O[-1][-1]<=0;/ P2 m  V" k3 D# x& R" H9 F% Y" t$ O
                  O[-1][ 0]<=0;, n, w3 a. ]% C% ^, P
                  O[-1][+1]<=0;
6 D  S& t8 X! }4 T( ]  D                  O[ 0][-1]<=0;" s5 b. A! T% e$ b8 I  P0 j) _
                  O[ 0][ 0]<=0;
8 X* H6 c0 U8 C8 A* c8 q+ N. k+ K                  O[ 0][+1]<=0;! n* G& t/ l( {; P' e7 h
                  O[+1][-1]<=0;
' r2 G, G. |8 g4 M0 u' E( S                  O[+1][ 0]<=0;3 ^: y# Q2 Z. c4 g
                  O[+1][+1]<=0;
: T- A% f# i  b3 E* c           end5 b7 f# L+ w( ^6 v; z' q4 y
        else
4 |( }, j9 p8 K8 P6 O" @" G) y        if ( shift_en )         ) u# {/ v5 W, O6 h; R9 S* b# }
        begin! J. i9 I: ?* J' n$ I$ L
                abs_D <= (abs(Dx) + abs(Dy))>>3 ;
$ Y: A' s) J' j" y4 y( s' B        
9 t  I. F- p1 @; C5 d                Dx        <= -$signed({3'b000, O[-1][-1]})        //-1* O[-1][-1]0 e  j3 O: E/ ~6 y8 [
                                +$signed({3'b000, O[-1][+1]})        //+1* O[-1][+1]
0 H3 j+ E' S3 T  X2 r, y8 _' h1 @                                -($signed({3'b000, O[ 0][-1]})        //-2* O[ 0][-1]
: |/ \% O  T1 q5 j8 H* T2 D                                                <<1)" g  G: I+ q" ]6 L& e
                                                ! l& M7 o2 Q0 d+ T' M4 ]3 d
                                +($signed({3'b000, O[ 0][+1]})        //+2* O[ 0][+1]; h: ?# Z6 {8 Y) O$ X0 D9 A% W  Y  F9 v9 n
                                                <<1)
) V1 K2 k4 `- B                                       
2 f6 G. F* s+ u( K                                -$signed({3'b000, O[+1][-1]})        //-1* O[+1][-1]4 `' v! J, U5 ]4 K5 a, m
                                +$signed({3'b000, O[+1][+1]});        //+1* O[+1][+1]6 [7 E1 D1 ^2 C# a. F
                                2 W% E1 `2 l7 e) T* h
                                
: E* T# l+ t% x                                
& G  ?4 O& r( F                Dy        <= $signed({3'b000, O[-1][-1]})            //+1* O[-1][-1]
" }" Y' h: k. b) Z* P                                +($signed({3'b000, O[-1][ 0]})        //+2* O[-1][0]: ?1 n+ Z9 O) r2 P+ h( G
                                    <<1)               
5 \. I& y9 u: l4 d! S4 N: l3 R9 g" w* F                                                     
& r6 E6 `+ S/ H, @* R2 m. X  J3 \                                +$signed({3'b000, O[-1][+1]})        //+1* O[-1][+1]2 |8 ?; [$ t& }5 o. l- Z$ R
                                -$signed({3'b000, O[+1][-1]})   //-1* O[+1][-1]
9 z. a6 z6 H' A; ~* u+ U                                -($signed({3'b000, O[+1][ 0]})        //-2* O[+1][ 0]
' e! u3 r! e/ X( [2 l+ H( u                                         <<1)5 H; Q$ i: l: a+ q" d0 _
                                        + {. t: y0 w7 |5 C" s# w/ d
                                -$signed({3'b000, O[+1][+1]});        //-1* O[+1][+1]. r  i1 a4 K6 ^
                                5 h  |) m( k% U& k- E
        O[-1][-1]        <=        O[-1][0];& r  j* h! I9 v; `
        O[-1][ 0]        <=        O[-1][+1];
: P3 K* l) w$ |3 X        O[-1][+1]        <=        prev_row[31:24];
9 L8 ?+ y/ C! J/ _$ a! U# o        O[ 0][-1]        <=        O[0][0];
: A/ h7 R( k8 {' M6 Z- H        O[ 0][ 0]        <=        O[0][+1];7 {8 k7 p, N4 H, ?/ e% H
        O[ 0][+1]        <=        curr_row[31:24];
3 Z* F  I  |6 C* X  l+ h        O[+1][-1]        <=        O[+1][0];
% ^4 y2 o3 j; y1 [. ~        O[+1][ 0]        <=        O[+1][+1];
! e+ I: k8 ^: H$ K7 J5 @        O[+1][+1]        <=        next_row[31:24];4 g6 ]) S: q% \& z" f4 D' d
end, b5 S: f' q. w: Q% U+ O6 x: k
/***********************��ֵ����***********************/
# I5 z( M% i+ c% }# X//assign D1 = abs_D < 60 ? 0 : abs_D  ;(����ijЩͼ�����б�Ҫʱ�����ã���ֵ60�ǿ��Ը��ĵģ��������ͼ��������)7 w. N( B/ l* X% \" v! r  I0 I
/*****************************************************/: y1 J4 P: e( I3 |2 b/ }
always        @(posedge clk_i)
, o( d) W/ ^; {  o, O/ Z( \        if(shift_en)        
& o% t" a* W/ K+ \* R- I$ R           result_row        <= { result_row[23:0],/*D1*/abs_D};' `! @( I0 t; V7 ?- [" j8 U
endmodule
4 ~# t. M. y' f( Z6 {
; c1 U, n0 @* q6 V6 t) E# V: J, A) {! ?# a- }2 X0 c8 M- a, j
machine.v$ t% J$ d: t: n2 q8 a- ?

4 [9 T- t: b6 R% R8 S8 V- ~2 V. e2 |( s) B

& X2 ~& Z& n9 t`timescale 10ns/10ns
# c& a0 ]. Y0 r/*****************FSM***********************/
, \" s& k. t! O( hmodule machine(, G5 A: s, s3 X7 r- x4 Q. l8 N
               //input1 Y5 b& P+ W) k+ S$ n( ?
               clk_i,
1 R# G/ N5 u. u! M; C% L               rst_i,
: M; M  G  c& x# J+ h               ack_i,
6 l6 ^+ L# P! y2 w+ t- {               start,+ A7 _9 a+ }3 |! D: k5 p# S
               //output; e- B. y$ m7 C" G: o3 k" ?, C
               offset_reset,- O( x6 T5 h: ?
               O_offset_cnt_en,( r4 h. C( b; k6 x" w+ _0 A
               D_offset_cnt_en,
: k; P$ @4 i9 `+ Y               prev_row_load,
8 L6 w2 r% x, N) Y; f               curr_row_load,
  I1 x- N% R0 D9 x& |               next_row_load,
, c  |  I) T( G, {: d: J& k               shift_en,
2 `) t( E/ h) h- }9 W( w3 o               cyc_o,4 C, p8 \# A' Q1 Z, B' X: _
               we_o,9 h. p0 U7 l6 ?% b
               stb_o,. j9 J) g; |7 X% B( ^6 F
               current_state,
" j4 p; f" [4 s1 R( g8 e               done_set
: r- r  l5 j0 `6 R' t               );, l& n6 K# f( i$ |- |( x
input  clk_i;
2 z3 w2 {$ Z$ ^0 B/ ~3 p6 h  n$ pinput  rst_i;# x2 y" m4 ^/ P* Y4 t
input  ack_i;
' w# \. z. J6 x6 u/ H4 oinput  start;
; g( [- j/ l3 `6 }" s6 b# koutput  offset_reset;5 t1 y. G0 q  y3 A& K
output  O_offset_cnt_en;
2 H$ K1 M4 x- t2 l- t) `output  D_offset_cnt_en;
4 p+ p8 c$ m8 F2 ]6 Ooutput  prev_row_load;        2 u, c, ]- c4 i/ Q. N% r
output  curr_row_load;      : T- h$ I% G" P: `3 S
output  next_row_load;   
( g7 c" ~; `! }+ eoutput  shift_en;" I" ~% O$ M  q/ w  e/ u
output  cyc_o;7 Q, l( `# j. X: M9 ]" ^( _
output  we_o;
/ i7 E, p3 r! L% A5 O% @/ u, \output  stb_o;$ k9 j& j' G6 s3 v* l
output[4:0]  current_state;
. i# p& ]' w$ H# a$ N8 J% a: \9 poutput  done_set;3 |: |: t0 w6 Z% B7 N
" V/ g6 z/ r; ]& H- W8 b) D0 Q
parameter WIDTH = 1024;  
2 ^8 Y: C4 X  ^8 T2 l$ vparameter HEIGHT = 768; 4 m1 u0 P7 f  r5 c

) Z, T$ M; x2 @( M# ^parameter [4:0]        idle        =5'b00000,
: w, n% H! u7 e7 g+ F* A( \5 L& A                                        read_prev_0        =5'b00001,
; }4 W4 b* B- H$ g                                        read_curr_0        =5'b00010,% }+ n  ]/ i( I/ P! n
                                        read_next_0        =5'b00011,
5 @8 i) A" e6 \                                        comp1_0                =5'b00100,# y. V1 r6 D0 ?2 P7 n" i/ v
          comp2_0                =5'b00101,
/ b7 e# h) D5 `  v6 K, H                                        comp3_0                =5'b00110,
" B4 W! x; u5 u7 r% i3 S9 S  }5 m                                        comp4_0                =5'b00111,
$ v5 _, j# e- g* b                                        read_prev                =5'b01000,
/ E* F: c& @! g/ Y# W                                        read_curr                =5'b01001,& {0 Z& R& K8 ?* ^5 G7 m
                                        read_next                =5'b01010,
4 \- {# o5 @+ f- W, `                                        comp1                        =5'b01011,
# V: q7 _5 W' _. |* U/ [                                        comp2                        =5'b01100,
! M4 Q& J- h$ W9 @+ L3 q2 c( Q                                        comp3                        =5'b01101,
3 O6 S" @* t' f                                        comp4                        =5'b01110,
: ~: y3 _; N1 m9 f: H                                        write_result        =5'b01111,
' y7 W- Y3 K  }( ~3 @% S2 C                                        write_158                =5'b10000,
7 T" }" Z& G% @8 {8 d                                        comp1_159                =5'b10001,# D4 I& _' R! s, a6 D8 \8 C8 H/ u
                                        comp2_159                =5'b10010,
6 Q4 h( L4 }% _" X# d                                        comp3_159                =5'b10011,
; g4 R0 J" G0 P                                        comp4_159                =5'b10100,
, ^* {4 w/ y. ~& ^, x4 V( _                                        write_159                =5'b10101;6 C$ Q2 `2 a, f# }5 ~) _
                                       
1 t3 T) l- |4 h% \! ]. e* \6 Jreg [4:0] current_state,next_state;
! `: T# ^: y6 M  w" ?; Q5 ireg [10:0] row;    //0 ~ 477;. R# k" i7 \/ Y' U. J0 n
reg [8:0] col;    //0 ~ 159;
2 }$ M, j  w% @  w " }2 j- R8 z3 E4 i' V9 i
wire start;2 d. |% K; Q+ [# ]
wire stb_o;8 z0 A) y$ d# X
reg  offset_reset,row_reset,col_reset;( {$ W# |+ K7 o/ O9 o5 n) W

' x. h+ ?7 V' Xreg prev_row_load, curr_row_load, next_row_load;: X; O* P% T8 I7 F
reg shift_en;  f/ E0 N6 }" Y$ ~4 @5 ~. |( M
reg cyc_o,we_o;
% A& N" [- m$ `" b; p& oreg row_cnt_en, col_cnt_en;* B! P8 @8 \6 w( ?6 r" I) H: Z' s
reg O_offset_cnt_en, D_offset_cnt_en;
  T" A- Q% B9 @reg int_en, done_set, done;4 A" b9 F; E0 ~& E* U$ J( _1 P0 M* l6 G

0 V/ c+ A* B( o0 E: V, P; Q 5 w" Y4 G7 _: N
4 a; H1 m. w% c' i
always @(posedge clk_i)                //Row counter
  D4 y: h1 o0 L9 |- k" l! a        if (row_reset)        9 c0 \( g7 R: [+ \! J9 ]
                 row <= 0;
% p& _  O# `& t$ J5 p/ H: |* s, [        else ) s# G3 m+ H7 m5 o  J. J9 o/ Y2 @
         if (row_cnt_en)        
5 o& c' a. a+ \, v* K            row <= row + 1;) ^* f" G7 s4 x  l1 X) K4 \  i  G

0 @# R8 ~* t+ Kalways @(posedge clk_i)                //Column counter
/ F+ D3 c" d' L( j9 a' l        if (col_reset)               
. a# N* C/ V0 t4 L" C           col                <= 0;; C9 i& a* q* ?8 _
        else
% ?: \$ o0 A1 y6 E3 y3 o          if (col_cnt_en)        
: F' z# d$ u- h: B3 U1 }' Q9 ]; E            col<= col+1;
' R8 ~' ?, X. H' {
7 c" z2 \. q& h7 R* C+ z# U% s//fsm
7 l$ Q3 z8 m+ s6 ~always @(posedge clk_i)                //State register
3 x) g& @  N' `, R4 B) U/ n        if (rst_i)        
' J" [0 K. [0 ~9 M3 Z0 v6 d9 h- K" u' u           current_state<= idle;7 Q% b; n% f  N3 z
        else          [6 |; \6 u: G) a; l0 K
           current_state<= next_state;
% l% J2 [  i8 g" z9 C        
* R$ D4 |0 w% P. c  C' }: C( ]" a3 Calways @* ( F4 ?1 ^" n2 E) {7 V
  begin        
( G% k5 [" l" p4 S        offset_reset                =1'b0;
  P7 X( A/ q9 O( W; _  row_reset                        =1'b0;
) a/ A1 Q) ~4 K, `) g) U        col_reset                        =1'b0;
4 l& j6 z7 s8 J3 i0 x        row_cnt_en                =1'b0;
' K' ^7 _) t4 \! p) ~        col_cnt_en                =1'b0;
& w' r9 k8 [( K1 V        O_offset_cnt_en        =1'b0;
9 ~5 S% Z  Y" O5 b! `5 E1 F/ a        D_offset_cnt_en        =1'b0;
- b5 f9 Z. u% v! V, d9 t1 e        prev_row_load                =1'b0;
0 A0 L$ n" Z7 X, F/ d( e        curr_row_load        =1'b0;
- E0 @" y# L8 A1 R        next_row_load                =1'b0;
* I7 H" x! ~' }7 @4 j+ D' {1 `        shift_en                        =1'b0;
3 `( [! B6 r# @/ ~/ H" c( Y2 B- ?        cyc_o                                =1'b0;* X' h0 X' P$ D/ _6 u
        we_o                                =1'b0;
" f0 Q2 n  z+ R- I# `% j* K5 d        done_set                        =1'b0;
3 d% q. G9 Y1 q7 k4 F. D$ z. A        
$ \) L5 x9 e' S- S  Ccase (current_state)# |% L1 _/ G9 W0 {- u$ ?- g
idle: begin
2 u  I2 _- R8 t$ |7 s8 x            cyc_o =1'b0;9 G6 `( n4 i# ^& d# y& L& Q
                        we_o =1'b0;
, q3 d- P9 v4 w1 l8 N/ I3 Y) D: M: j                        done_set=1'b0;- w6 f6 u7 l$ `
                        D_offset_cnt_en =1'b0;5 M: ?0 H' g+ `7 a4 z
                        offset_reset =1'b1; 1 M8 }* w& B) y
                        row_reset =1'b1;9 ^& t) |0 Y! V$ y3 y2 e" c
                        col_reset = 1'b1;
. ~0 I* j3 l: m; \* ?* A* P5 z                        if (start)  7 i1 O- Z1 K+ v+ L- q
                          next_state = read_prev_0;
: e3 w! G/ _, h7 f6 M- ?1 e7 y                        else                 6 x2 H& s- Z8 |6 h; q1 \
                          next_state = idle;
2 H: S+ l+ a6 h- w8 U      end
9 H8 R" I, v+ k# ^! Z          # ~4 Z6 e5 S- w/ n  s. R3 P$ l. o7 X
/*************************************************************/         
& n8 |: i: _; l- Pread_prev_0: begin5 |) @4 n8 p+ F
            offset_reset =1'b0;- v# ?- R7 u" ]+ R! f2 X) D
            row_reset =1'b0;
9 i$ c. j( p6 a            we_o =1'b0;
/ N/ m9 E8 n6 D" p8 n8 ]# K            row_cnt_en =1'b0;
) ~. p6 k: |7 Z: w/ m/ y: E            D_offset_cnt_en =1'b0;$ ?# }  r2 [# B) f  f- D# ^
                        col_reset = 1'b1;
! b  C. R- @$ ^# |9 _& b                        prev_row_load = 1'b1;" R. j  a0 U1 [; [- T0 f
                        cyc_o        = 1'b1;$ Y$ M4 ~3 i' ]. ]! X3 T, [+ R
                        if (ack_i)  # ~4 X0 x% h6 F& _8 R+ c# b
                           next_state = read_curr_0;: I9 T1 v, f% z' I
                        else        ; F$ A- A6 Z7 M9 b6 ^- Y7 M$ @7 e
                         next_state = read_prev_0;# `9 W1 S/ i" M* a  D- E
                  end
( K/ _, i' C. j$ m/***********************************************************************/                  
% L0 Y& N" d3 B, a' n* c/ R) m; Cread_curr_0: begin, Y( k& }" K- n6 Q; p
            col_reset = 1'b0; ) f! q/ `" o- ]: g  u4 @. P. ]# l! ?
            prev_row_load = 1'b0;        5 z. i# I2 n# e% l8 C" u
                         curr_row_load =1'b1;
" o: [2 E7 F/ [7 T- e                         cyc_o =1'b1;9 c; C/ Y& `- Z: M' b
                        if (ack_i)              //read mem
/ D( v9 C7 d" f- `) h  z                           next_state = read_next_0;' t4 _: T5 R. n
                        else                 " w2 X# ]3 b' q5 I& ~3 ~9 C
                           next_state = read_curr_0;
0 y+ |! B0 A9 r8 s                  end: }. L% t, U" k2 T/ s" R: t+ N9 P
/*********************************************************************/6 D/ e) F  w+ w2 r
read_next_0: begin9 F4 f# [; _* o2 I+ V
            curr_row_load =1'b0;) c& G" p1 A% V+ Y' }# D; A
                        next_row_load =1'b1;
7 W3 w& D" f" H3 G                        cyc_o =1'b1;* B$ f+ t, s$ I9 A9 V* e2 P, j. f
                        if (ack_i)                    //read mem��cnt+=1
7 y' y8 y* N9 b                          begin
$ S1 O+ k. \0 [2 H$ O7 I                                  O_offset_cnt_en =1'b1;
1 ~5 A! U) P- M1 y                                  next_state =comp1_0;
* H  o. Y: ]2 D0 {& B  Y                          end% H/ S  Y- i; e$ K* S
                        else
4 d# e) d9 N) z* {2 U* I                           next_state = read_next_0;
8 F) \( J( c; @                  end3 P1 r& d; p5 T
/********************************************************************/, Q  X$ L- R( I& B9 ]; v) p) J
comp1_0: begin
) l# k2 j8 R1 {. U! E. M: [  z: j            next_row_load =1'b0; , X; Q& F) @" p( {1 p8 @
            cyc_o =1'b0;
! I+ [) m8 j. A3 d            O_offset_cnt_en =1'b0;& ~9 ]( C3 b  Q* g
                        shift_en =1'b1;
* [9 \0 |1 ~* P% \( ]+ d/ p6 a                        next_state =comp2_0;0 _$ k& ~% z# ]1 c" F/ P
                  end8 {. u% I- P& y. v/ k# Q2 `: E! s
comp2_0: begin
0 X6 R2 k* E5 F2 _0 v; l, {2 j0 ?                        shift_en =1'b1;, z' S- z; M3 U0 F9 r% d
                        next_state =comp3_0;. U: b% J8 `/ h3 x$ _
                  end
8 B' L2 l; K  U, j( X" u, Ycomp3_0: begin0 l, y( C$ ^% K. k
                        shift_en =1'b1;
5 K6 r/ d/ j* A" ]6 G6 ?9 J7 n8 ^                        next_state =comp4_0;: ~/ z6 g; n. e$ l/ j' E
                  end3 w0 h; b" b! }" j: v! R$ O# R
comp4_0: begin. @- ^: P$ b1 ]) p$ T# X# I
                        shift_en =1'b1;
2 w+ |- \; x9 W4 V                        next_state =read_prev;& k! m- \) a1 t& i6 K
                  end        
. w4 G" x$ a9 u' p/**************************************************************/
: O3 ^7 Z2 |: @# i4 g9 [read_prev: begin
* }1 N. S4 T. N* V; d            shift_en =1'b0;        ; Q. O; s; D; H
            we_o =1'b0;
( K5 k4 T& c# [2 W8 |; G; v0 `9 {            col_cnt_en =1'b0; 6 |. m1 T( a0 R
            D_offset_cnt_en =1'b0;
* b; F9 S- \9 i" A7 N                        prev_row_load = 1'b1;* w: d' |& s* w# f9 `0 u% y' [
                        cyc_o        = 1'b1;
2 E1 l0 q) O+ N! W# U& t                        if (ack_i)  
+ e! ?, Z' u" B6 C                           next_state = read_curr;
; f7 u1 e) R$ v+ D! M                        else        3 e: a2 r8 m) H9 e
                         next_state = read_prev;' O% c3 \4 m; m* G% @
                  end           
( \3 ]2 K; `& S6 z5 `7 gread_curr: begin        3 G! V) K- A, [
            prev_row_load = 1'b0;8 P: J2 ~' J; F0 ]$ {9 z& u8 ~
            curr_row_load = 1'b1;
  U4 x5 ?. G( `+ b                        cyc_o        = 1'b1;
1 f! ~7 d* X1 Y8 P8 V9 d                        if (ack_i)  + h9 i2 \, U; V6 i
                           next_state = read_next;/ [: S: j8 t" |' H0 i8 V+ R- n, q
                        else        0 D1 ?! G0 k  ^2 d5 f
                         next_state = read_curr;) Y6 i8 \* S/ Q7 A; V! \
                  end        
6 k$ w) u( B- {* n' l+ Pread_next: begin4 s* F" s6 C1 g. C0 _6 t
            curr_row_load = 1'b0;        6 s1 U$ f$ l' I
            next_row_load =1'b1;
$ R, s' t) O/ q& C% u: f                        cyc_o        = 1'b1;
) I/ R- T- G6 X- v                        if (ack_i)
% A; d! p, @/ C9 y2 R                                 begin6 Y' r2 H  a7 r& Q' `/ C4 T
                                          O_offset_cnt_en =1'b1;  ( H- M" x% M. ~" V# {. ]
                             next_state = comp1;
: v3 D; \5 z- ~: {& i                           end
3 V& F" S: h) A& b                        else        
# ^1 S) w, l5 B( F6 h/ G' Y, ^                            next_state = read_next;
; n1 K% k/ d* @6 H0 ~! w                  end7 f' y. l1 x+ o5 f7 W" i
/************************************************************/                  % X6 v& g* w) Y/ R3 g
comp1: begin. A7 g* I9 l# v' T3 C6 \2 U  b
            next_row_load =1'b0;5 ]9 F/ j% Y% p
            O_offset_cnt_en =1'b0; ! s' {# |1 G% V4 ?; L$ m, r6 u  {$ X
            cyc_o =1'b0;$ a4 Q3 l# o8 U7 I
                        shift_en =1'b1;1 d% q3 f$ B% U% f& t: I( l
                        next_state =comp2;* _: F( l* z( K1 Y1 L$ h
                  end                   ( r9 o2 Z- F' U
comp2: begin* y" p( b% _9 a3 C* Q# Q
                        shift_en =1'b1;: [, l% ^6 B5 E, h. P( X2 k
                        next_state =comp3;9 B; b1 D. Z* m$ I# F
                  end$ W  F% V) N3 [# G) q
comp3: begin
0 P5 r% K  _- l6 _$ [                        shift_en =1'b1;8 D9 q' y, d" s' n6 I( P
                        next_state =comp4;
3 E% {/ m3 ?7 p& F) J                  end                  
  N3 k8 u( V; Z* i. u- k9 |comp4: begin
/ e5 Q; U' v3 [; v) ?! Z- G$ Y                        shift_en =1'b1;
, f0 v* B+ T6 `  A6 I9 Y+ \                        if (col ==(WIDTH/4-2)) * d2 Z4 T" M. _; V8 M9 l% q
                            next_state = write_158;8 f% J) k/ C9 M9 T) Z/ A
                        else                         # c7 C8 V  a" X# t- O, ^
                            next_state =        write_result;* R  d2 \- G+ f' d
                        end* _3 o8 @0 c, ~1 C% x
/********************************************************/
! H: _' ]# P6 l) s6 p* k% R2 hwrite_result: begin
4 L( |7 Y$ s% H5 Q+ w& U# P            shift_en =1'b0;
: S! M) J2 ?# c# m0 D) x3 @/ T                        cyc_o =1'b1; & L  X8 @7 r. u" ?" k9 w7 ~
                        we_o =1'b1;) Y! G% v9 z  B! e
                        if(ack_i)        . J, b# ?- K% H; [3 [
                          begin
4 D, P2 m6 t- z5 j: l/ r9 v# G2 P                                  col_cnt_en =1'b1; & z* y9 S4 X; n
                                  D_offset_cnt_en =1'b1;; Q( x9 e( e4 M' k9 P$ v7 R
                                  next_state =read_prev;7 J" y/ O2 Z9 s% t
                          end
% e; b3 e! b% i; m8 n                        else   J" K7 @* X2 F1 r0 L" k) P
                           next_state = write_result;' s& ~$ |* j" G6 e# e
                          end( j" S; [2 m4 h
write_158: begin
2 L6 K) {9 P1 g            shift_en =1'b0;/ t' v8 |0 ^3 O$ h0 j% o
                        cyc_o =1'b1;
; N; S5 c! O* U3 d. u7 W* f. w                        we_o =1'b1;4 r/ b% P3 T% t: @0 o3 e
                        if(ack_i)        
1 ?4 Z2 f) k! y                          begin
8 E: W0 M; y+ T5 h& x                                  col_cnt_en =1'b1;
* I, X* Y2 G4 b& G                                  D_offset_cnt_en =1'b1;+ z# e+ X, H" T! @$ X4 _
                                  next_state =comp1_159;
5 w8 K- I) ]8 l# |                          end
$ Z+ r% ?/ f0 H; w7 I" M5 ?                        else 9 q3 _* ?. O6 V! ]* ]
                            next_state =write_158;( f1 v- r) A( F, ~+ d; b/ x
                        end1 ~' i' o3 J# T  @- g" T! E8 ~
/***************************************************************/- w" Y' m+ ~' N+ T/ [
comp1_159: begin                              //pipeline output stage$ ]9 z  r& E1 s. ]; o
            col_cnt_en =1'b0;
+ k7 a  m* X9 H. m' l9 a4 r            D_offset_cnt_en =1'b0; : a) N0 i. F, v' ?& m' X1 B
            cyc_o =1'b0;, S* q7 K6 L! K4 ~
            we_o =1'b0;
$ w- r$ \7 _( w4 N& G                        shift_en =1'b1;) U1 u/ r0 {7 q6 x6 h5 _  u% F$ [
                        next_state =comp2_159;
+ c0 D; |+ S7 w                  end                        
) J( R7 S  N  b) o# e: U/ U. J# Q2 bcomp2_159: begin; M3 s% @$ O# S% J: S6 ^
            shift_en =1'b1;6 @' l' p) a; x$ ]" W/ K
                        next_state =comp3_159;0 j% g: T6 R7 h& e: J
                  end                                
* G- c/ {1 v$ w' s) Qcomp3_159: begin
" Y! i/ z* I3 Z; x            shift_en =1'b1;& v2 D0 h, e& L( g; o5 r, y
                        next_state =comp4_159;
( |( G. n2 D- M3 B                  end        - `1 m" P% Y) {% b" ~; C
comp4_159: begin
4 n. m. a' B" Q3 ^% f, @, Z            shift_en =1'b1;
1 V! N" D4 G- d                        next_state =write_159;
) U$ o6 H- L: ^# w: p                  end                                                  , I4 `) M$ i3 f' _; b2 t) T+ O% }
write_159: begin
9 A7 ~5 @% n, Y( d8 g            shift_en =1'b0;" }7 H* ], H. f8 F
                        cyc_o =1'b1;
% Q# Q$ G' p( C- A' @) a7 t, K. O                        we_o =1'b1;
- C  U- r9 N  c+ J& k                        if(ack_i)        " [5 P7 K( {" U. T( _7 j4 `% d
                          begin6 b! I  n, H; H# Y, |
                                D_offset_cnt_en =1'b1;! }- u$ @# a! w6 J( M  i( U
                                if (row == HEIGHT-3) //sobel done; U0 U( n$ ~& h
                                   begin
$ g2 j4 X# c0 p7 i* B  ?$ L6 P( T                                           done_set =1'b1;
" E, X3 |% V: z- c: a                                           next_state = idle;
9 }  m/ C% q9 P. {% ?; O                                   end) ]! t7 m# Q- k2 C
                                else
( w9 f5 @6 J2 a                                  begin; d. I) U0 [% m# k+ r& y7 K
                                          row_cnt_en =1'b1;- Y) K: s" J  S
                                          next_state =read_prev_0;
/ S  j4 D3 Y/ T) O0 c# L                                        end2 \  a( x4 [# ]* F: ?2 t2 \5 d; n& C
                         end
! N& e$ N8 s9 `0 [                        else 7 R2 I8 L. y* f1 H7 x6 G  w) Z: O. d
                           next_state = write_159;1 K, f4 I3 f6 \  U  l  n* p% r" [/ q
                        end
, y7 p8 L2 D6 w' s        endcase
) W! |$ Q' c$ j) L4 j% kend
& X6 Z6 Y: t* ?/*******************************************************************/
, K* T6 ~  y1 _- Q& t, c 6 c% u  i) z# @: l! O
assign stb_o = cyc_o;
. Y  P& |' J3 D* q9 I# K% U; Z ! J' Y! p/ L3 m% \
endmodule
' K7 X. X# B  f, d) C4 S& S
2 }% k/ }4 J0 Z& p: c1 d
) j( d( N8 X) T# e# D+ w& ~) F3 Z/ usobel_slave.v
: U4 c8 c8 k4 X( K- q5 C% e
: `6 B3 Y; d( w, o$ j0 Z8 X; W5 ^) Z5 h( [
4 S# c4 E0 }: R/ D; H
`timescale 10ns/10ns
0 n$ K* K" t, \/ s- F) f' }' t; N( @module sobel_slave(/ h8 v  P, y8 ~# x
                 //master slave share i/f
# l; x" ~0 t, T/ ^. d: ], B& A                 clk_i,' T' C* |/ R' J9 @" u' m/ X; \
                 rst_i,' d4 r5 i- [6 D
                 dat_i,
' L) a" K0 A4 C8 m; m3 h. H                 dat_o,              
* ~$ {& E" j9 _; G4 N7 L4 u* C                 //slave i/f+ B: O3 d  h% y$ f' j
                 cyc_i,% A/ }8 n& P) [& D3 J
                 stb_i,
. H! M$ v$ J8 Y- }  q/ u                 we_i,
# n( A7 y* Y0 H* ]( W                 adr_i,
3 Q1 K: r: D* _& P7 e( ^! a% L                 ack_o,  x" `: T; [# D
                 //output
3 T6 o& X2 ?  {% T6 ?5 `: o                 start,
5 \. B3 @& M- c- w6 P8 F( }: N                 O_base_ce,8 u1 G1 U6 J' S2 _0 V* z" U
                 D_base_ce,6 a& `& L! ^- Q0 ^5 A
                 
2 @% j) p+ J3 u/ v2 Y: k: ~                 int_req,
6 q* G7 p( C+ ]) ~  m8 {% e                 
, @# l( }, w: C2 t( H% a                 //input
: \+ f1 s( @% x; U0 v$ R& {                 done_set,3 U- r# M; I0 c8 `
                 result_row! X+ p, `2 W3 [  l, C
                 );
) P5 _3 R0 G& @2 F3 k) D. ~; I% p, `                 
. _8 d# t4 L% p  J+ p0 cinput  clk_i;. @. x/ R2 a3 \: c# b
input  rst_i;1 u9 X' n" e9 _+ f: P! X
input[31:0]   dat_i;, {2 p* H( D# n' j" _
output[31:0]  dat_o;' @! |0 T: n  ~. N9 v# c

* T" N( |4 `( m( x- [& Qinput    cyc_i;
9 l( V% D9 \# Q) s  Uinput    stb_i;- g- G- j0 A7 Z/ Z6 |
input    we_i;
% _5 B- S4 Y. K. S- I5 t& Z& ^5 iinput[21:0]    adr_i;
2 M7 v5 A  V$ j2 joutput   ack_o;
+ A) w2 k/ {1 p  M: r1 G# j: doutput   start;
3 Q6 b0 e- R4 B: v" F7 }output   O_base_ce;4 Y' D5 F, i/ g2 k7 I
output   D_base_ce;
% y2 e9 D5 n: c3 doutput   int_req;
$ R& K! [$ U. R" n( w! Vinput    done_set;
3 z5 Y1 P( N0 `# |; Y8 {input[31:0]   result_row;
8 H0 j, t' z1 |) k
, J0 J% O* U8 b& Hreg int_en;
$ X- N3 w: d: D% wreg done;  {" d3 \/ U  p% p% T0 y/ _
reg ack_o;8 i) _( n$ E9 b# w3 E2 M5 z
reg[31:0]  dat_o ;   
. n# v* e* K- I9 B , E; v. ~. N: M7 F# x4 @
/*****************************************************************/
4 P& b3 X% o3 L4 L9 ~, ~            
& R0 ?) ~, G0 V- b" G3 w: Q7 E; U9 Zassign        start                = cyc_i && stb_i && we_i && adr_i[3:2] ==2'b01;//adr_i[3:2]
% \# c/ q3 E& P$ H) i 8 R0 [5 W* R3 J$ |' \, D! |
assign O_base_ce        = cyc_i && stb_i && we_i && adr_i[3:2] ==2'b10;
1 e! r0 {& s, ]# W9 q: G7 \) K
. h' g: y0 a2 o1 `0 uassign D_base_ce        = cyc_i && stb_i && we_i && adr_i[3:2] ==2'b11;7 }. E' W+ K% X. t' z; R

" q6 U& i) [, M; N% U/*************************************************************/
- u7 `6 b" x, ?2 s# K * N7 x/ B- a8 o) b9 ], J
// Wishbone slave i/f
$ p$ Z8 z+ ~6 i" e- l4 T
4 N, p. F" u" |' r) balways @(posedge clk_i)//interrupt reg
8 X7 `, N' ^& o5 ?/ D        if (rst_i)4 e0 e& f5 X5 b# B; l6 ~% W% q. m
                int_en <= 1'b0;8 x; K- C, ^6 U" O7 Y
        else
3 e4 b- z, l0 t2 R( ~% z8 ^- _            if (cyc_i && stb_i && we_i && adr_i[3:2] ==2'b00)3 l9 _, u  Y+ G. b. ~, c% ^1 k
                    int_en <= dat_i[0];
/ U' j- D/ E" p3 k' v8 L  i/*****************************************************************************/                        
4 [' ^' @4 T, U4 `  Y- B                        
6 w; I- c, s. D% _! h2 e, a" J" Ualways @(posedge clk_i)        //status reg
6 g. P8 ^- S( |( C+ h        if (rst_i)7 @0 T% }* z2 ~/ e' ~
                done <=1'b0;
8 Y/ E/ k$ e* h+ z' i& [        else / v7 @: S: z9 {  C" ^: G
          if (done_set)9 I' p" `  m' g
                // This occurs when last write is acknowledged,4 Q% K0 z- _: L9 j
                // and so cannot coincide with a read of the # i' z# D  K: m/ `4 M# \1 J/ u
                //        status register
- s/ c7 v! D0 T! N                   done <=1'b1;1 t1 j, [! P4 ?/ p" {7 R5 s  |; [
    else
* U2 L: c- G. M3 G/ n      if (cyc_i && stb_i && !we_i && adr_i[3:2] ==2'b00 && ack_o)6 b. o' [+ K! o& m7 F) q
                done <=1'b0;
1 K3 v! ~- \, ~* L# [                        # x# C+ w( q" @+ B) W5 I
/********************************************************************/                        $ `* B, F( P7 J% q
                        
  \& `. \$ ?: h  J: R5 d& O* S4 K. Kassign int_req = int_en && done;6 P) d0 j4 G2 `8 h" T+ K
/*********************************************************************/' }7 u6 ?6 X2 A- o6 c1 ]( L
always @(posedge clk_i)' F+ m. G6 Q- H7 N1 C
        ack_o <= cyc_i && stb_i && !ack_o;" R5 [6 i' J  f+ H
/*********************************************************************/        " B5 w, `& e  G2 n) ?0 Z; `+ j
always @*
/ A0 }/ q- ~3 H, Q/ ^        if (cyc_i && stb_i && !we_i)
$ _, J7 A8 }* X3 Y* a) m; L                if (adr_i[3:2] == 2'b00)
- ^% w2 N7 s( i2 Z                        dat_o = {31'b0,done};// status register read
& Y/ z( z/ R4 n/ h  D' a$ C( y                else
/ i& m3 b$ K/ o3 F                        dat_o = 32'b0;        // other registers read as 0
% t# p4 I6 C+ Y; z" t" t* W3 W5 [        else 2 f' a. \( B) S- R* m  L
                        dat_o = result_row;        // for master write- a5 ?3 m, O" i1 l  l) H
endmodule                        : W1 J0 Y, ~. o
  [6 K8 x; g5 r8 _+ Z

, E) T+ `2 Z: v3,硬件的功能仿真
  h% Z, b9 b3 C2 Y在进行仿真之前,我们需要编写相应的仿真模型和相应的图片预处理,后处理程序。* l% K" ]  w7 H' ]; U6 B  y8 Y

4 J4 ?- k- q# P& e下面是前仿真的结果:从中我们可以看出硬件的执行时间是23562270个cycle,约23.56ms。
$ F- z, {3 ]4 t2 P. J5 Y8 q$ x4 v% }8 n; @

4 Q+ B5 z+ x( d2 d2 E6 ?6 {# i( S9 x9 T8 W$ R, \! k
1 i9 a6 W6 q9 ~# u6 y$ c

! e0 d/ D1 U, e6 c& X7 V1 p8 o在做功能仿真时,我们就可以得到一个处理结果了,原图和sobel处理结果对比如下:
9 p# ?2 K! Q8 W+ H; o
9 E  Y! i) t' ?+ B+ U' l
' M9 {5 m9 l' C2 K1 G9 z! m! r; P8 J8 ]  y
, w% e* K9 O6 R6 _

1 C4 t9 t9 E* ]7 Q功能仿真的具体操作步骤,请参考bmp_post目录下的README文件。内容如下:6 ]! V' m! X$ R+ ~

" p* \2 X4 ?' _& o, }4 I* ]" g
1 \. E9 X5 B1 D  t6 K6 t* p9 R& ^3 d3 \
/*# {- ?4 E+ S( G2 }, D; Q# e' O! T
* Rill create
* ?2 a5 d0 F- U- u* rillzhen@gmail.com8 c" k. K2 r7 n3 l1 s" H
*/
/ o( {! a' u! T9 `+ e$ w- e. p
( X* y# ^. `2 r' s: }( [1,保证原图为1024x768的8-bit的sobel.bmp
5 b& V, V' R1 b( m" t0 {/ y2,运行read_bmp.exe,生成bmp_dat.txt
, x  B/ J3 n1 }6 I" B3,将bmp_dat.txt复制到verilog工作目录,运行仿真,生成post_process_dat.txt
* L! u8 w3 X2 `0 Z4,将post_process_dat.txt复制到本目录,先运行bmp_process.exe,保持bmp_process.exe运行状态,再执行bmp_bin.exe,最终生成sobel_rst1.bmp,为最终处理结果。
9 g6 n) g  C& M8 v: S1 v
4 i- p. G4 _) }$ r& e" y
% @" y9 P6 [7 ^3 i& R% z需要注意的是,本例中处理的图片为1024x768的8-bit的bmp文件,如果想处理其他尺寸的bmp文件,需要修改一下testbench.v中的相关内容即可,如果想处理其他格式的图片,则需要重新编写对应的图片预处理,后处理程序。/ e1 O( O% n/ n! K" z& V" _
" ^7 i, A' x, ?3 j% X6 L3 y5 N

# `/ @3 W0 C0 V7 c& j/ q$ i) E
* ?& ]2 B; ~; ]* N  h0 J3 V4,硬件的时序仿真0 @; k. N; \2 M, r9 o4 r5 a
在最终在FPGA上运行之前,我们还需要做一下时序仿真(后仿),这时就需要用quartusII在综合时生成包含延迟信息的文件(*.vo),还需要quartusII的库。
5 f) K+ }- Q, z: E" K
3 Q  Y4 g% I2 b% a+ g) F. v我们用quartusII将sobel模块的所用可综合文件进行综合,会生成sobel.vo文件和其它vo文件,比如sobel_min_1200mv_0c_fast.vo。
: f' f7 z! k5 g# |4 N
1 D& ~, r2 |6 H3 G4 P0 e在后仿时,用到的quartus的库文件有:cycloneive_atoms.v , altera_primitives.v。. X+ H. U! u1 C$ ^! m1 R9 p8 C

% {! O" K- d, t( F& T当然,还需要仿真模型文件:testbench.v ,cpu.v,memory.v,arbiter.v。$ M% `% V2 Y7 r# L; s7 q- ^
1 B0 h) _6 v' w/ t# Y& C
+ E1 l) I+ r) H( p
! y* r& Q* |$ ^+ v
经过近半个小时的仿真,结果终于出来了,按照前仿真的步骤,也能得到相同的处理结果。' r* V5 C) t0 v
2 J( E2 `: A" h4 H  u
这里需要注意的是,如果用sobel.vo做后仿时出现hold/setup时序不满足的问题,可以使用sobel_min_1200mv_0c_fast.vo来做后仿。
; T9 m$ v3 @5 O" p: s
3 e. Q3 q8 j6 d) w后仿真的工程,我也已上传:+ R4 |. n. O/ j8 c

; _, J1 N' y/ ^" Phttp://download.csdn.net/detail/rill_zhen/6371857/ C7 y2 r2 M$ C, c. H7 u! l. J; K7 Z
8 n; B, n6 z% D0 W- L$ f
/ p5 h( Z0 S$ X: E

/ G9 A2 J4 `0 _$ t5,软件实现0 v5 K1 \/ w) X
为了便于对比硬件的加速效果,我们需要编写相应的软件程序,然后在openrisc上运行,得到运行时间。
4 G3 j( T4 Q2 j7 ?3 k
1 w& P  u& [% k下面是C语言实现代码:4 {# ]" Z0 q- u9 ~& F

/ O9 A/ ~: `' g, j5 Pbmp.c:; g9 i$ `" G: b: a& @1 K/ i
  F$ Y; w3 `/ G" k: R( D5 o* v: Z
6 o0 ?* D# w* M1 u4 H# T) z4 ]( i

0 G: f/ K0 t6 D; w; Q/ ^#include <string.h>   
6 b* z5 b2 `: R, `' `#include <math.h>      % g2 @, K: {4 X5 W
#include <stdio.h>      
3 ]6 ]$ b$ s8 F1 J#include <stdlib.h>      + q* w) k3 S* S7 B9 h0 s/ ], u
#include <malloc.h>   
: G7 {6 J4 i3 G$ X7 K#include <sys/timeb.h>
% A( O  ]- \: u9 p$ r#include <time.h>  4 u0 ~4 Z1 P) W) H* S
* z( i' C: Z( i$ W
typedef  struct {! Y$ O) [4 ]5 z/ \- c5 ?  x
        double  real;
' R3 p9 @: H- P" x% Q! a        double  img;
" J3 g) r7 B$ o/ ^        } COMPLEX;. V$ E$ X& |" v, Z
typedef struct
  P' _( o2 D, U# M% c5 B. C7 I{/ U7 m3 S/ i) e; `. B- B
        long tv_sec;  ?9 S# C2 A' ^& b2 G" O
        long tv_usec;
+ I' d. G  p: {+ c} timeval;8 m0 y5 t' V0 m# c  h
' i! {) C+ Y+ l9 [
     L( b7 a8 m- f' p+ [( M# [9 Z- L+ K
typedef unsigned char BYTE;   
- [, b8 p' o: jtypedef unsigned short WORD;   
- \" |+ c3 q. c" H+ Z  R! p4 Utypedef unsigned long DWORD;   
; D% p( `/ m+ F3 ttypedef long LONG;   / ~0 ]- |+ [7 D7 f0 K
  
/ [* R& ]" T& k8 _# Z 6 s3 S$ M7 U% W0 Y1 y
//位图文件头信息结构定义   
6 i( j! `1 v5 J) R* Y% U//其中不包含文件类型信息(由于结构体的内存结构决定,要是加了的话将不能正确读取文件信息)   
0 t" E# Q. p6 x* I8 {  1 Q5 J1 O& _5 Y/ [& R3 U6 f9 z) V
typedef struct tagBITMAPFILEHEADER {$ R6 r: B; O5 h$ R* e
        DWORD bfSize;           //文件大小   % l3 d: @5 Z. q9 {9 U
        WORD   bfReserved1;     //保留字,不考虑   ( `/ `: i* M; S8 K$ s
        WORD   bfReserved2;     //保留字,同上   
5 T' {3 {# K6 X        DWORD bfOffBits;        //实际位图数据的偏移字节数,即前三个部分长度之和   
5 t3 I5 Q! h  j1 {} BITMAPFILEHEADER;   
) X6 i: Y5 r% z. r6 D0 Y  , c" Y9 D& ?3 @# _$ P
  9 Z0 Z1 E$ f( M+ c9 w
//信息头BITMAPINFOHEADER,也是一个结构,其定义如下:   / H4 K: R4 W6 g$ a
  : a( S' ]3 F6 E4 s
typedef struct tagBITMAPINFOHEADER{   
& n8 H8 Z3 a  S6 e" `5 C* `* t  t# \        DWORD   biSize;             //指定此结构体的长度,为40   
' [4 k0 l; i. `8 A        LONG    biWidth;            //位图宽   6 v/ m4 T0 Y4 U. L
        LONG    biHeight;           //位图高   & O( {, @) o& @
        WORD    biPlanes;           //平面数,为1   
6 C  F) e/ k/ l* P0 Q        WORD    biBitCount;         //采用颜色位数,可以是1,2,4,8,16,24,新的可以是32     E/ K3 ~: h5 x2 l
        DWORD   biCompression;      //压缩方式,可以是0,1,2,其中0表示不压缩   6 c  \3 w- I$ A- t% Y) }4 a
        DWORD   biSizeImage;        //实际位图数据占用的字节数   ! R5 G. ?' E* y
        LONG    biXPelsPerMeter;    //X方向分辨率   ( ~, Y: [1 z( T
        LONG    biYPelsPerMeter;    //Y方向分辨率   
3 W+ m  T' V: V& j' Q  d        DWORD   biClrUsed;          //使用的颜色数,如果为0,则表示默认值(2^颜色位数)   ( U3 u  h# g* n# n. o0 W
        DWORD   biClrImportant;     //重要颜色数,如果为0,则表示所有颜色都是重要的   * J; t: T0 w1 o6 t) @
} BITMAPINFOHEADER;   
4 x" k5 O8 ?3 Y3 o) ~- t, w3 j  @  3 H) r+ s  k8 |8 O* t! a
  % l2 Q# X' y; w* K8 x1 D
//调色板Palette,当然,这里是对那些需要调色板的位图文件而言的。24位和32位是不需要调色板的。   
, v' D9 a4 k1 Y//(似乎是调色板结构体个数等于使用的颜色数。)   
( n2 m0 ^$ ~5 \/ k1 b% F( r" V2 i8 b5 l  
2 I" m/ T2 [* N. r; ftypedef struct tagRGBQUAD {    6 D9 u. [& n* B' U- T) N2 J# U, Q, E
        BYTE     rgbBlue; //该颜色的蓝色分量   & B9 s" S0 j5 A& Q( O
        BYTE     rgbGreen; //该颜色的绿色分量   $ f; F  m5 Z  m" V$ q
        BYTE     rgbRed; //该颜色的红色分量   0 U! a( O& m9 j
        BYTE     rgbReserved; //保留值   
4 O* P* p5 _/ D* }: n1 N} RGBQUAD;   
: q. V5 B) P+ q* V: n, u+ x) f$ d, O  
* x+ ]. h+ v3 Z+ p' G  
9 I  e9 _5 o, S' [+ a- B  
, t4 C' L' P$ f- k" W) gvoid showBmpHead(BITMAPFILEHEADER* pBmpHead)   4 B& s6 n( W9 B. u8 M+ N! }
{   2 f% |* ~2 k0 ]( `* M
        printf("bmp file head:\n");   
1 F; r& R$ K4 w- c        printf("size:%d\n",pBmpHead->bfSize);   
7 H7 c0 h, Z  ]" k: M0 l6 O: L- ^        printf("reserved byte1:%d\n",pBmpHead->bfReserved1);   
" Q: {* D7 x/ ^& A' \& K; F2 y" o        printf("reserved byte2:%d\n",pBmpHead->bfReserved2);   5 E9 o& v1 v, @. `
        printf("offbit:%d\n",pBmpHead->bfOffBits);# A( b' y4 G( O0 e+ n- D
}   
0 ]; [8 H4 u1 @# S0 D, P4 ^  
2 y( t4 w/ W6 P9 L7 H  % v; S: ]/ i0 m5 X
void showBmpInforHead(BITMAPINFOHEADER* pBmpInforHead)   
4 _8 v1 p" x6 p) y# X  \{   4 f' U5 a( @$ V" c/ j( X
        printf("bmp info head:\n");   
9 e/ |, U, W" i3 a        printf("structure size:%d\n",pBmpInforHead->biSize);   ; u4 G+ B& D( X, h7 I
        printf("width:%d\n",pBmpInforHead->biWidth);   
1 R/ f: |0 l: z# k        printf("height:%d\n",pBmpInforHead->biHeight);   9 z3 X" }1 s9 @/ r: I
        printf("biPlanes:%d\n",pBmpInforHead->biPlanes);   * n( q' T, V; n7 @6 k1 n
        printf("biBitCount:%d\n",pBmpInforHead->biBitCount);   5 h: T3 j: A) \4 ^
        printf("compress type:%d\n",pBmpInforHead->biCompression);   " D. e7 f4 `$ U! p% b
        printf("biSizeImage:%d\n",pBmpInforHead->biSizeImage);   
+ D, K9 N" t, h* B, k& W        printf("X:%d\n",pBmpInforHead->biXPelsPerMeter);   - K* o* _# r8 W2 G0 b& {/ O
        printf("Y:%d\n",pBmpInforHead->biYPelsPerMeter);     P" ^: T5 t0 t
        printf("colour used:%d\n",pBmpInforHead->biClrUsed);   ' V8 S% q! p8 C0 C  L
        printf("imp colour:%d\n",pBmpInforHead->biClrImportant);   
! W1 v- g" k; }! |7 d' d: \. C}   2 _" B% L6 z. E( p7 P
  0 O; b# ]- U+ P6 g4 M: {
void showRgbQuan(RGBQUAD* pRGB)   
7 P7 g. ^! A. D! E{   
/ Y8 Q" H. u+ R9 Z, @: J        printf("(%-3d,%-3d,%-3d)   ",pRGB->rgbRed,pRGB->rgbGreen,pRGB->rgbBlue);   : ?8 @2 p) Z, L2 s
}   
' t# S5 e* Q/ M4 s7 }  
/ b2 D8 ]1 S* A# W* P& k  t# K- W4 Zvoid sobelEdge(BYTE* pColorData, int width,BYTE* lineone,BYTE* linetwo,BYTE* linethree);0 b6 {; h) m  N: a

* c! A- ]% r; i% iint main()   
! i8 {. J, C' {* l9 P{   6 |: q7 K+ U0 ?/ @& Z+ z! k
  timeval tpstart, tpend;
; N3 Y" j; F: `  double timeuse;
: e3 I! q! |; G# p    w; F4 J. F$ o/ l. s: N
        BITMAPFILEHEADER   bitHead;   ) E: d" M7 |8 S
        BITMAPINFOHEADER bitInfoHead;    1 P9 E* \7 N5 j# p- v: r, B. s
        FILE* pfile;   0 l+ }& {5 O; z# ^% \$ {+ P
        WORD fileType;
* s+ m4 L# R, ]         / E" B5 \# @3 t8 G
gettimeofday(&tpstart,NULL);$ t4 N# i3 n  Y( ]! t" M- O; z

& A2 _* y$ G4 |        pfile = fopen("./aa.bmp","rb");//打开文件
, m, _$ S: m5 G* ?        if(pfile!=NULL)   ' t6 x+ m( ~- W! P* n0 B* h* j
        {   " |' ^5 Z; {* ?, [& E1 G& C" d2 m! j6 I
                printf("file bkwood.bmp open success.\n");   5 ]" m; w" g8 Y! o' t' R4 b- ^
                //读取位图文件头信息   4 m: k2 a3 ]: J0 Y) c& M
                fread(&fileType,1,sizeof(WORD),pfile);   ' o- r0 T3 M8 I# o$ T1 f4 L
                if(fileType != 0x424d/* 0x4d42*/)   & ]! D/ P2 |2 k3 N' \8 h; X$ H
                {   
7 Z4 [/ I" l+ j( o# ^4 k- W6 h- E- ~                        printf("file is not a bmp file!");   8 S) K, b- K% u/ }* b' k/ Q
                        //return 0;   
6 O. v0 W+ S- |: z: o2 c                }   
  T1 e1 \+ z  Q% n8 e6 d               
3 o. u$ B0 g' d1 C9 j! r6 a. A                fread(&bitHead,1,sizeof(BITMAPFILEHEADER),pfile);   2 f! j$ {- S- |* }1 U2 Y! R
     ' r% c2 Y" V2 m& ^4 u
                showBmpHead(&bitHead);   
5 p$ b" _3 {/ N; S# {                printf("\n\n");   
; Q4 R5 V4 X  x$ F% E) ]" [2 x; Y  ) ]: v' I4 f7 |7 F# B
                //读取位图信息头信息   + e1 [( C& u" O7 ~1 v" \) Z, R
                fread(&bitInfoHead,1,sizeof(BITMAPINFOHEADER),pfile);   0 j& M5 X  z# a
                showBmpInforHead(&bitInfoHead);   
3 C" j: |( b3 {& V) |; e% Y                printf("\n");   
9 G7 T- e2 s- A1 \8 s        }   + c: G8 d* N( q0 p& ]. z
        else  6 l: u% A" i- H' A% g
        {   
4 q' C$ Y. q( D6 E& G- y                printf("file open fail!\n");  0 r, X; F  L/ X8 Q

" W) W5 j  P6 _                return 0;   - T$ P5 |4 T# l  e! y. w
        }% v! N" G# g4 A  p9 j. }3 ]
7 F$ k( [" `/ c5 ?* J; `2 m
; s+ z7 [/ d1 h' q" d2 e
        if((bitInfoHead.biBitCount!=0x800) && (bitInfoHead.biBitCount!=0x8))
! c& i; L) e  m        {* ~' X7 V: e- X7 o7 |2 i7 @+ \
                printf("not 256 colour bmp error!");( s5 F8 r2 B' r, R: c; C
        //        return 0;
0 o' @% g" }& P: x9 [        }. b! U9 K1 w' W( L( p8 Y
        
: \9 t3 `' ^4 z; b. Z: O        FILE *pwrite=NULL;//写sobel之后的图像
- x2 Z4 ^/ i! o/ F- n/ g  g% u" D/ M) @        pwrite=fopen("Sobel.bmp","wb");
2 a( ?5 f: }) n0 p2 ~; N' ^7 @0 J        if(pwrite==NULL)6 ]- S! ^3 T( Q+ y& G
        {
; A: j- l  ~6 g/ f  m                printf("new file fail!");
/ \  z) l% z$ S        }$ n9 s5 l& e1 O/ ]% y) ~
        fwrite(&fileType,sizeof(WORD),1,pwrite);* v6 u; h8 r/ M7 E+ g4 b0 N
        fwrite(&bitHead,sizeof(BITMAPFILEHEADER),1,pwrite);
1 P8 w6 s" h* x% F4 i        fwrite(&bitInfoHead,sizeof(BITMAPINFOHEADER),1,pwrite);
7 V9 O4 Y4 j+ C* U3 M0 R
- S9 H6 u) c# C7 z6 C, ^: m* I $ v% D3 f" W& n/ S- G7 v' ?9 X
//读取调色盘结信息
5 R/ e! {) c3 u
4 _8 @, A9 K' {1 F: K, X1 D  P        RGBQUAD *pRgb ; ' }! b! @( F, G8 f  x$ h8 H
        int i;
* C* P) X5 o, c, r, u        int rgb2gray;
/ R5 j' x1 ?! _1 o) r        long nPlantNum = (long)pow(2,(double)8/*bitInfoHead.biBitCount*/);//   Mix color Plant Number;
  ?) F- K2 d! h        
! r: i" m; m$ G4 I- ~: r) J        pRgb=(RGBQUAD *)malloc(sizeof(RGBQUAD)); . L) d% I" J6 T; }3 t
        for(i=0;i<=nPlantNum;i++), u2 H, Q. I* n$ D
        {
: k3 Z( S9 s8 s( [% D) w; E4 {                   7 s7 i! d! @% n! L" s5 R
                memset(pRgb,0,sizeof(RGBQUAD));   
, L5 u' n' _  A  v, R                int num = fread(pRgb,4,1,pfile);          3 T# a& ]( f7 }( D, u* y1 G' W
                rgb2gray=(300* pRgb->rgbRed+590*pRgb->rgbGreen+110*pRgb->rgbBlue)/1000;! I6 a, O  V$ c% M  B
                pRgb->rgbRed=rgb2gray;
  N- C5 P, q& A  N% X, U5 K                pRgb->rgbGreen=rgb2gray;
7 S  W( Y7 g" t) s: W( F8 y8 B5 @. T                pRgb->rgbBlue=rgb2gray;                & A& c! y2 c- Y" d3 j# D' b
                fwrite(pRgb,4,1,pwrite);               
/ z3 l. X  _1 f% e- a        }
* H/ J) p. r/ {+ P0 {0 x% P2 T 3 R# C: a. x1 a1 n
        int width = 1024;//bitInfoHead.biWidth;   ; ?3 A, ~- W' l! @! b$ x
        int height = 768;//bitInfoHead.biHeight;
- h3 c8 l7 t: B) l 6 Z5 C1 N/ q+ S) |7 q. h& P9 V

6 b3 w0 U) p: ~/ F+ F2 i
: K$ t( ^, p4 j9 m' m" W! I3 ?        BYTE    *pColorData=(BYTE *)malloc(width); //ad 0 q# a7 k3 m. s; F8 m
        memset(pColorData,0,width);//ad3 n& ]6 D6 h% ]6 P* G/ k7 }
; Q+ D; ^0 k, M. s
        BYTE lineone[1024];
8 {; w( d3 i( P! n* d# Y" U        BYTE linetwo[1024];
' P- i5 K; R7 N        BYTE linethree[1024];
- @6 R+ T, f; J1 B( H
$ g, R5 W* f, l& v- w, N8 D# U+ b( E. @        int num=0;9 q. |) L0 n8 I; X2 [" q- W. _: _
        int j=0;5 \6 K5 h# X4 C) d9 b
        for(num=0;num<height;num++)
& g2 }6 v4 T/ Q5 @        {* C/ ~$ \7 z+ r$ _) }
                fread(pColorData,1,width,pfile);
5 N* a  b$ \6 Z8 K                if(num==0)
$ r, T& ?+ D6 I  v2 L                        {
" r* R& p( t7 f9 {/ ]                                for(j=0;j<width;j++)
/ g" t- x! W2 M1 Q7 O; n" \                                {
% w3 J# T' X: a. b/ x                                        linethree[j]=pColorData[j];                        
' n  w: U, P) L5 j+ W                                        pColorData[j]=0;# W5 \/ L7 _9 }8 H6 {
                                }
, W7 z! N1 _2 G% |: v3 P                                        fwrite(pColorData,1,width,pwrite);
: f% h4 J$ I$ ^8 B  k3 ?* ~4 A, Y9 T0 ]                        }! Q1 V: T, M+ U& K; W
                if(num==1)7 z% Q; f0 u9 ~, ?3 r0 E( B6 A! k
                        {
: `8 \/ H) ]$ J: N                                for(j=0;j<width;j++)+ F1 F2 o5 a% o1 I
                                {
+ E4 V. m: l: S                                linetwo[j]=linethree[j];7 u9 P& q7 @6 `1 k& h8 t/ v
                                linethree[j]=pColorData[j];                                : P# K2 j) y/ u5 ^
                                }, D. F; {- c2 e/ a
                        }               
, V5 R2 X7 M# P0 Q/ Y# z2 I                if(num==height-1)
4 d# _( i) l$ _6 O' i6 ?                        for(j=0;j<width;j++)4 \$ o/ H. @, L9 B( f0 C3 J
                                {                                                               
7 d5 D! G) s5 [) d: Q' N  Y" {5 H                                        pColorData[j]=0;
) \3 ~# ]8 H" a. ]                                        fwrite(pColorData,1,width,pwrite);* a! D9 S: `9 N# {+ d0 c0 e; K
                                }                        
3 h4 n7 |0 w7 T* c# [. I0 [/ T                else
! J% R- H$ H- ~- s& V                        {                        
! K1 P, F  \4 b. o: U" s                                for(j=0;j<width;j++)- y8 P2 H: y: P2 }) k1 Q& I
                                {3 Y: i- {  Q) M
                                        lineone[j]=linetwo[j];6 }& j  P( X' H
                                        linetwo[j]=linethree[j];; v! w' t# u; b) s
                                        linethree[j]=pColorData[j];; T" }  ~+ v7 u6 b/ z  |3 H
                                }
0 S: j9 A6 v! K. [( w+ F: U/ |2 S                                        sobelEdge(pColorData,width,lineone,linetwo,linethree);
* b4 `1 Z, g& b. p, b9 o                                        fwrite(pColorData,1,width,pwrite);
- T$ J0 _( O+ [                        }        
! c. g/ y/ W6 b4 o- ]5 t! C) r        }4 T. ^# D7 a* e
        fclose(pwrite);
: C  Q3 h' I9 T/ V  f3 ~        fclose(pfile);   
/ l0 T6 t5 t+ u& z5 o4 U4 p( ?        if (bitInfoHead.biBitCount<24)   
2 @% Y% l1 M. v0 Q" k        {   
% f( \! }6 T5 |8 d4 Y1 y7 u                free(pRgb);   
" |4 V; c; W: ^( X        }           
4 q5 ~4 n/ }) U: C: [        free(pColorData); . e! L9 L; ~1 H8 ]
          9 a* }6 a: h3 j7 H6 b
        gettimeofday(&tpend,NULL);
( m6 Q1 ?6 a7 y, z        timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+tpend.tv_usec-tpstart.tv_usec;+ k4 M5 F, N0 z# B" L
    printf("sobel_soft Used Time us:%lf\n",timeuse);  
) W, Q3 Z! c  M5 K        return 1;
" [$ a8 ]% ~) f9 R6 u4 x) V}; x% P& A. I! s' G% e  d9 M2 L
void sobelEdge(BYTE* pColorData, int width,BYTE* lineone,BYTE* linetwo,BYTE* linethree)
! e& B* o3 Z' S" k{
; s9 F' Q' W. l) F        BYTE area[3][1024];
$ }$ j. b5 p9 W: a8 _# Z        int i=0;& A% a' V4 ?( [; y. {% x  @
        int j=0;
% `6 H5 |: O" T- E6 a% H# ], w) D& Z        for(i=0;i<3;i++)$ z4 H) ]9 J# G- _# |9 |
                for(j=0;j<width;j++)
2 }' m- u; k: d6 F2 z5 ?                {, g( _0 M8 s% ]7 N$ j7 \
                        if(i==0)
; _/ Q# _( b  w# z+ N( Z                                area[j]=lineone[j];4 A/ k( B0 h+ B0 i4 W; V
                        if(i==1), t3 E* Y* l; D
                                area[j]=linetwo[j];5 C' b% a& C( Y
                        if(i==2)
6 r( P0 [% O. E# [& T3 r                                area[j]=linethree[j];
# s0 x5 k* ]+ ]# x& A9 c                }0 X  }6 {: @2 n  k9 o7 j
        int temp1=0;. z1 I$ s6 Q( M7 j4 S% C# `' f# O
        int        temp2=0;
! N& E% I( I' m3 y4 ]* y        int        temp=0;
' v7 o  S& n  O8 \8 G$ m        int *tempM=(int *)malloc(3*width*sizeof(int));1 ^4 T) P5 a; q; Q. {& s1 Y  n
        memset(tempM,0,3*width);/ a% D8 l) S! H+ i8 w
        
2 }; f1 s5 Y+ _- N+ Q* c4 w6 u2 f        
2 l2 e& t& @$ U8 b" {; z  ^        int m=0;, k# f5 T& k8 `2 L& h8 H
        int n=0;/ o" L, b2 D( _/ X
        for(m=0;m<2;m++)
" m* m) X" p) |7 \, F                for(n=0;n<width;n++)) i. ]1 f. O3 ?7 p, O6 h$ }
                {# z1 E0 E0 n# _- W
                        if((m==1)&&(n!=width-1)&&(n!=0)). h' R8 l9 ?9 b% `/ j
                        {
3 L% w. a0 ?* h( a) N5 t0 H                                temp1=area[m+1][n-1]8 @1 V: |1 m: `( C1 p% z3 k
                                                                +2*area[m+1][n]
. X3 H; O" k9 {) ?                                                                +area[m+1][n+1]
9 u: Z  b* n7 [5 |0 @8 E                                                                -area[m-1][n-1]/ ?7 d. T! c4 g
                                                                -2*area[m-1][n]8 b. p( G: a6 S, K& j; `# @
                                                                -area[m-1][n+1];7 Z' \; f) V: A7 G9 W
                                temp2=area[m-1][n+1]
# K0 \1 o& c/ g, s                                                                +2*area[m][n+1]# \2 a1 E3 `& r" r4 y8 `0 x/ M
                                                                +area[m+1][n+1]. o1 m; w; \2 p, L2 l, ?% E
                                                                -area[m-1][n-1]
8 l3 t1 d5 Y1 H$ D& m$ R+ O8 x8 U+ p                                                                -2*area[m][n-1], \) p5 c: C+ `) A
                                                                -area[m+1][n-1];% t9 a! \8 h8 h1 J7 }: y% M
                        //        temp=(int)((double)sqrt((double)(temp1*temp1))+(double)sqrt((double)(temp2*temp2)));
% P, t# q3 ~$ R, R: U) B, p* U                                temp = (int)(abs(temp1) + abs(temp2));% O- l9 a9 N" q+ R$ }( o8 c, O- Y3 p
                                if(temp>255) 2 m2 g1 z* [% K8 D$ c4 z# t* _) Y& X) t6 W
                                {
2 j/ r; Y# d# t8 f( N. D* H: ]4 r                                        temp=255;. M0 Y6 ~) J( f; V" o
                                }" d0 p0 s. f1 I5 C
                                if(temp<0)
2 s2 p! i$ M4 ]$ |8 l. S- r) R                                {* c1 g& \8 U2 d0 j( M( G8 x, V/ p
                                        temp=0;
0 h3 z  i) g- z6 z7 m" I3 \: @                                }                        # `) z. u: U; w7 p) R& p
                                tempM[m*width+n]=(BYTE)temp;; r. `( F0 R3 B' w7 M! a1 M2 D' s& j
                        }
1 R8 z; z) H$ v1 j& H$ t* H                        else
' F/ B) [- ^2 G# b                        {3 V5 J: n0 y( T
                                area[m][n]=0;
$ a2 M& U) _3 `' o$ i2 D* z. |) \                                temp=area[m][n];
1 ]* q& E5 l* @) C# q2 e) u                        }
) o2 M4 l3 A6 S) `8 t! R; m                        5 a; t0 P1 Z: ^
                }
3 n; V* l9 M6 f        for(n=0; n<width; n++)5 C( a  y1 ^8 ?2 A% o. Z
        {( \8 B5 d; [+ |# n# O# X, M
                pColorData[n]=tempM[1*width+n];
; B% r: ]  S* |+ u9 {        }
# U0 X' L' v$ j7 u        free(tempM);, `3 E6 s. J- z* V' r( h. Y
        return;( K6 c3 i* Q0 \" y: S
}
  S, w1 a+ `+ M( w) K
' Z- |( k1 Y2 D- T
2 L0 r. O6 q/ M: k# T. ^4 U' W( @
$ R+ Y- E' U# `1 `4 C4 T
' y; p# p' d# C9 S; B; g/ V+ V+ ?在虚拟机下编译:or32-linux-gcc bmp.c -o sobel2 s5 A- }7 B6 x1 M
) P5 [$ l2 A1 [) }8 f* {3 ^- k% t
copy到开发板上执行,得到打印结果如下:从中可以看出,软件执行时间为17972.718ms。时间对比=762.76倍。硬件加速效果明显。当然,实际情况比较复杂,不可能会达到这么多。
* f" X  Q6 W* H" f1 B/ ]* y* q. c4 ?2 t6 J. m! [0 B
% ~; h" U# b3 i: J' a

) V; K! Y2 {4 W) d; F! w- E3 F2 z( r8 z+ g

8 b/ j; [+ Z% @+ I软件处理结果:与硬件处理结果有所差别,原因是处理算法和预处理有所区别,但区别不大。) i: @' p2 G+ z  y; J
/ W* m0 C" [; I# b

( y0 o  ~5 W+ [0 Z6 J. _  }+ g6 M% N+ m$ M+ m/ e

3 K) r8 q1 u: R1 `- ^$ ?3 o" y
5 S+ k1 v$ z# O/ _6,小结0 Y& \" ~. c2 I, j
本小节设计实现了一个简单的sobel减速器,并编写了相应的软件,与之对比,加速效果明显。
5 \- @2 K6 a" L: A: f+ g- T7 t! a! H+ Z0 b1 k1 R
, u7 x- i/ l( l, o9 \& g2 U
# D8 W% e: x1 ]4 D8 O
7 ]) g: ^" D' N- C$ l9 `2 d

. U. f- }9 T  Y/ w: _$ L5 W0 J

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-7-2 04:22 , Processed in 0.156250 second(s), 26 queries , Gzip On.

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

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

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