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

转——基于ZX-2型FPGA开发板的串口示波器(二) 

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-4-18 09:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

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

x
转——基于ZX-2型FPGA开发板的串口示波器(二)
' ]+ C, d: n5 V4 r( p; F; |
串口发送接收模块设计代码分析8 c9 s/ K9 h! H$ A/ B3 ?. o9 Q
1.1Tx_Bps_Gen

* j6 L/ s; S7 ?; v! P4 y
Tx_Bps_Gen发送波特率生成模块,每当Byte_En信号到来时,即开始产生发送一个完整字节的数据需要的完整波特率时钟信号
' |( H3 B6 I. i- M1 ^本设计,波特率支持9600bps921600bps例如需要产生的波特率时钟为9600bps波特率时钟频率为9600Hz周期104.17us生成9600Hz波特率时钟的核心思想就是对系统时钟进行计数,这里设定系统时钟为50MHz,则一个时钟的周期为20ns,我们只需要对系统时钟计数5208每计数5208产生一个时钟周期的高电平脉冲,即可实现生成9600Hz波特率时钟的功能。相应代码如下所示:
& Z/ G% |0 v, g) A; I
, \+ p) Z* D" A& q7 O
018     parameter system_clk = 50_000_000; /*输入时钟频率设定,默认50M*/
' o: ^4 D0 Z# l; T) _/ r, @
7 U. \& y1 l+ L4 A" I9 v8 y019
! d7 Y8 @3 a2 }9 V3 L
. P2 P, ~( G  \. E7 @; M020 /*根据输入时钟频率计算生成各波特率时分频计数器的计数最大值*/        
' p. l; V7 r9 b8 I: d7 ^( [
; R" ]% E0 i. z9 z" i, d- ^' y021     localparam bps9600 = system_clk/9600 - 1;
. P$ c% I, n; S) D$ `" x, {; p. a! c+ j/ j6 ^
022     localparam bps19200 = system_clk/19200 - 1;
2 {) e/ Q% R9 t# U; S' g# H# r% p
0 ]: m* ~3 K$ K6 S" a023     localparam bps38400 = system_clk/38400 - 1;
* s6 H$ X, m; T6 [4 c5 [1 L: I# L5 n! W9 m* @9 l
024     localparam bps57600 = system_clk/57600 - 1;
& h: }" E, e4 L% N7 ?8 V' p* q5 z
025     localparam bps115200 = system_clk/115200 - 1;4 v0 W( m% W! s; A5 }7 P; `" J

: Y- o) c/ [. ^. O) |! w1 f. G026     localparam bps230400 = system_clk/230400 - 1;
) @6 m' b" H: v. `" x- Q! Y, u
% B3 h3 W+ z, h027     localparam bps460800 = system_clk/460800 - 1;
) `9 O# ]4 E6 l+ w: T$ h6 U. B% B" [8 K
028     localparam bps921600 = system_clk/921600 - 1;      
# g: v. Z0 G( G) N  |9 ?7 Q! ]
029     - I$ ^5 @$ I8 p" w5 P
! I' }' u9 @5 f, @6 Z) d  m
030     reg [31:0]BPS_PARA;/*波特率分频计数器的计数最大值*/
6 h' T4 x' h  q- I7 L4 E- q
( C, l' A; b% v3 b. |0 S. Z# V0312 _+ D" @7 ]: O$ c
& x' a) u8 j+ H9 M: r9 I% e; J
032     always@(posedge Clk or negedge Rst_n)
* G- R* E2 O9 l6 T7 ?$ r, l) o( w0 A. B- P8 M- e" u. B" {
033     if(!Rst_n)begin. Q$ x. _$ m% g+ }

# B9 u; D) l  k) S. Y  E6 o4 s034         BPS_PARA <= bps9600;/*复位时波特率默认为9600bps*/
: t3 F; Z- }. x) A
: m9 s4 r3 {, G  Z' n: P& L035     end- Z+ }" c& }! s$ J& B

) r+ o0 I; n7 f036     else begin) n! Q7 i2 r- ^8 ]# |
. s" O- v" \, n: Y3 l- _& [! _
037         case(Baud_Set)/*根据波特率控制信号选择不同的波特率计数器计数最大值*/8 S) Q! T; F7 j! q) q
: X' J! d( r5 A& F& Q
038             3'd0: BPS_PARA <= bps9600;
# {  ~" s6 D) S
% |) s' e$ ]. x$ `' ~+ j. a039             3'd1: BPS_PARA <= bps19200;
2 t3 z( _/ u1 x# B
5 C3 E' l) Q( q6 v9 r" Q040             3'd2: BPS_PARA <= bps38400;
4 n9 t. I9 u- R* T; O
, L! N  \2 Y6 q, k# }1 K9 ~* J041             3'd3: BPS_PARA <= bps57600;
. p3 h) C: H" T. P* I" L( j$ W& W( K" ]) I) L
042             3'd4: BPS_PARA <= bps115200;
: I- O% M. Q: _6 I1 f- b3 z
: B* `) N9 H3 K. J8 V$ \3 e( D043             3'd5: BPS_PARA <= bps230400;8 H. M2 q& S5 X3 O! V9 |& o

0 z* M1 L9 C7 R" v. h044             3'd6: BPS_PARA <= bps460800;
# M5 C% W1 U1 _. w4 b1 k6 P+ D; m2 \* P
045             3'd7: BPS_PARA <= bps921600;            % `. z  C/ b& @; v

: f" x7 ^4 Y9 c046             default: BPS_PARA <= bps9600;
; X( ~# T" G  N# F# b! ]6 a6 x7 V/ c4 f3 C& n5 Z% ?- f2 L
047         endcase+ |% k- s9 [& _3 \) m$ [7 U
) }, I; @1 K9 W, F, h- s% o
048     end# X, ~! b" K$ R% d

7 b/ \" V) d; g8 I+ A+ v/ E) N049     5 s- z  b& q2 u0 }

! t* r7 r. r. w9 a" e% ?050 //=========================================================1 G- ]& B5 ?* L# m  {" h9 I: F

' ~( @) _7 ]# w% Q8 Z051     reg[12:0]Count;
  Q6 }9 d) p1 d& g8 H* x8 u
; |, q: z1 _. O0 g' _9 j052     + @/ |( C0 x! u# ~3 ?. q2 O" c

9 ]# w1 v7 J; `# s: d053     reg n_state;: \2 i/ i; d! }( M" E1 J1 ]

8 ~$ L" M$ u9 l; Q  D' `- z- r054     localparam IDEL_1 = 1'b0,
: k7 D6 G9 d, f1 E7 o$ q" e0 [
/ M( L! l' m+ D+ d055                   SEND   = 1'b1;( ~; j$ {! p8 J8 U" M0 e5 n

! ]+ N+ _% C+ L4 y( w056                  
% n' U- n5 y# w+ v! {7 H$ w% Y+ v! m# c! o$ q% J, j
057     reg BPS_EN;
, g: }2 u3 @! |. r
( V2 K) a5 ], |  `+ l058     : [- F: Z7 U, Y0 J: Q. x
  B( c! d% R3 j  I  u/ f- H) s
059 /*-------波特率时钟生成控制逻辑--------------*/  $ p; l) A; x8 \8 j" j

( W7 o, i7 H4 L7 O; F060     always@(posedge Clk or negedge Rst_n)5 N, N+ r. c/ [7 |2 k& R0 Z

3 k6 {* B/ z5 {7 c0 k061     if(!Rst_n)begin/ N, k5 Z! T2 t* P& j% j3 `

6 g, y; z! L% l$ v. D% M6 @4 }062         BPS_EN <= 1'b0;5 C: I/ g9 |1 X/ ]+ i1 c% V2 K
8 D, ?  X+ u) r0 f
063         n_state <= IDEL_1;
# N6 s( ?/ f/ r' O
( X- @4 u; G1 y: g  C064     end
% P0 w0 |& C0 |& y( @- w; |! C
3 W8 G- u2 I" M1 y, J6 L1 J065     else begin* S3 Y6 c) G$ e

- P/ G' S3 C# u; I066         case(n_state)+ b! Y% [' L2 u0 m

7 b' e- t, ^  d  z1 _067             IDEL_1:
0 a% R# `  T! @9 l# g* g$ t, T: ^4 K
  z: u4 l; Z- h! i* O068                 if(Byte_En)begin/*检测到字节发送使能信号,则启动波特率生成进程,同时进入发送状态*/: Q0 y3 i, K8 ~: s; W" z
6 B1 y5 t9 H$ q  m/ h( l
069                     BPS_EN <= 1'b1;" ?1 I- j  ^2 q$ i

4 J2 A5 D  ?' v2 F8 G070                     n_state <= SEND;
' o1 t: S  _" H, N2 w: _1 A, _. {# x
071                 end) l7 B9 B) h3 a( _6 U+ b  x3 H* y
. V0 s) O: R/ P& G8 n. ~; H  ~( D
072                 else begin
- _* N" a) D0 E! i
2 D& [9 V& w1 B0 f) z' z' v3 C- z073                     n_state <= IDEL_1;& U8 M! D+ H( F0 [

( n3 E' ?8 _, E2 p; o( r074                     BPS_EN <= 1'b0;
% I( w* Z3 U9 K4 N9 e, f" e* C, \$ Q7 M9 `+ V, z
075                 end
9 b0 w; Q' U4 N% M' v  C- O
3 R: U3 X6 z, K8 t+ V( V076             SEND:
4 m8 |7 k+ @# D' P4 K! M! L- {8 G+ C; }5 U- m, U8 V
077                 if(Tx_Done == 1)begin/*发送完成,关闭波特率生成进程,回到空闲状态*/# y2 z2 S/ d9 S

/ {7 H' G8 t: a2 x5 w: Q078                     BPS_EN <= 1'b0;
& i$ B! u7 A+ M7 X; l1 K6 v
; m+ j" ^5 }  L* E+ T2 Y* J, e079                     n_state <= IDEL_1;- U  S& ]$ h( _, E9 L

+ }9 X5 u9 K/ D! ~- R3 @2 |1 X5 a080                 end
3 k- a; i7 f  G
% }9 t# E& x: r9 w9 N$ F081                 else begin
7 q; |$ t% v: h  p! R4 F8 ?9 F% U5 z  S- w
082                     n_state <= SEND;
( C" Q4 v" ~6 A8 f; J- H+ i8 N: @" z
083                     BPS_EN <= 1'b1;% o7 X& \, V2 n8 B0 ]) E) @

( A, R5 K' M/ r# h7 l084                 end
. S# h8 e0 W! |% v+ ?1 I
# d! |# ]6 {0 U( u' g085             default:n_state <= IDEL_1;
7 v- u9 U4 V  u# h6 Q3 `" S8 c2 j  @
086         endcase
" O* p5 o3 D+ J$ `
# @; c8 p, g( b; Z087     end) T( ]9 v4 |: H% `2 p0 f9 Z9 X
3 {8 D3 X: a' w; e, @6 X
088  N5 r  c1 l2 }9 B8 Q- c& l2 q' M) `
3 ], ~' B, H+ P. Y, U+ L- A
089 /*-------波特率时钟生成定时器--------------*/ / |, _7 @* j* [3 `& _7 B

) J  Z/ D! U7 c090     always@(posedge Clk or negedge Rst_n)
9 k1 t7 Z" a3 q' z7 i) _/ `4 r
- M0 A$ Y; W& Y( {, Z8 c* b091     if(!Rst_n)3 ?' J8 H  Q# B& B

' c, W# g6 ?, E& k. a092         Count <= 13'd0; . V& |+ j( g- B/ s2 g
; C# T1 z7 U/ ~5 Y0 s
093     else if(BPS_EN == 1'b0)( j. e1 H  A% N+ \- }/ i, c

5 C1 O1 w7 \0 P9 |094         Count <= 13'd0;
8 s6 B* F) D1 b" O& A- S3 S! |2 d4 O! Y# U4 u* C( t
095     else begin5 i! W+ r' `  u9 C& a" K

+ U5 Z( Q: W5 I096         if(Count == BPS_PARA)) \( P+ V+ B3 Z9 J- r8 G' v

& w) H9 J2 R2 ]. d9 S097             Count <= 13'd0;6 ^: ]  c9 v3 @
) w0 u. Z& C1 d# c2 S9 g9 \
098         else ; e9 n+ ^; U7 p: X
% W. d' n3 q; _' e& T
099             Count <= Count + 1'b1;
- F% t+ r" I. z
3 k  M) _7 z+ F; o1 x100     end+ v, C3 i& A" h- I. }

1 p% s6 q5 ^# Y101     ) p% P9 x5 s, V

: f& K: \! @1 V: I9 l1 f, Z5 ?102 /*输出数据接收采样时钟*/  
" |/ k* p# f! o7 ]* D7 R2 b* t
4 j" \: `* M. S, ~% [' O! @103 //-----------------------------------------------
! ~# b+ T) i9 f+ e$ W. X  [
" e4 V* l7 R% k; j. y: S' C2 t$ `1 ^104     always @(posedge Clk or negedge Rst_n)  U) `5 v5 Y) |- u0 e5 ?

' y1 ^( X6 v5 K105     if(!Rst_n)
/ y  O1 u0 f- L5 y" c8 r8 t: O- ^
! q5 d; S  G1 j0 O106         Bps_Clk <= 1'b0;5 T" ^% i* w* u0 S. p1 `4 |0 {$ V

8 R+ P0 s, A+ C1 V+ `107     else if(Count== 1), c6 U% h/ q4 M# b! z5 H
3 [! X5 ]% I" k  J' c  @
108         Bps_Clk <= 1'b1;6 W+ d& D$ e9 P! t9 v0 }5 t

1 I/ P# n( b! |  t- K2 S109     else 1 M. I6 h. K4 i6 g) ]; O
- P; t: j% {8 O$ v8 j
110         Bps_Clk <= 1'b0;1 P# V5 {& j( W1 d* @9 t" X3 x. D
( Z6 S2 v- b& k+ n% Z, d! c
3 O0 k: g0 _, u* _. N' C
18行“parameter system_clk = 50_000_000;,这里用一个全局参数定义了系统时钟,暂时设定为50M,可根据实际使用板卡上的工作时钟进行修改。 7 z0 |6 V4 q- q. n) P% K3 J, S" M
所谓波特率生成,就是用一个定时器来定时,产生频率与对应波特率时钟频率相同的时钟信号。例如,我们使用波特率为115200bps,则我们需要产生一个频率为115200Hz的时钟信号。那么如何产生这样一个115200Hz的时钟信号呢?这里,我们首先将115200Hz时钟信号的周期计算出来,1秒钟为1000_000_000ns,因此波特率时钟的周期Tb= 1000000000/115200 =8680.6ns,即115200信号的一个周期为8680.6ns,那么,我们只需要设定我们的定时器定时时间为8680.6ns,每当定时时间到,产生一个系统时钟周期长度高脉冲信号即可系统时钟频率为50MHz,即周期为20ns,那么我们只需要计数8680/20个系统时钟,就可获得8680ns的定时,bps115200=Tb/Tclk - 1=Tb*fclk - 1=fclk/115200-1。相应的,其它波特率定时值的计算与此类似,这里小梅哥就不再一一分析。2028为波特率定时器定时值的计算部分$ P' {' A; I3 p$ ^5 P6 D. p! |9 d
为了能够通过外部控制波特率,设计中使用了一个3的波特率选择端口Baud_Set。通过此端口不同的,就能选择不同的波特率,此端口控制不同波特率的原理很简单,就是一个多路选择器,32至第48即为此多路选择器的控制代码, Baud_Set波特率的对应关系如下:
4 q; m; C9 ?5 J: B/ ^" p
2 F0 u$ q2 o* ^) N5 o/ E000 9600bps8 @2 ]! r8 J- X

  r" Z) w1 }7 `. {( g$ u: |* }% r001 19200bps;
1 `' {. p" ~4 w7 [+ X  \) B* H) t# w$ c5 r! B6 Z/ \3 P
010 38400bps;) j, C) ^: S) u$ K
6 a; F- u7 B# }
011 57600bps
/ T. [' `  U8 `, B4 B- z. [- ~
$ b- ~0 [1 ]* \. @" q100 115200bps
* p3 w! v( C& d7 K
. x) a' u5 n* l( d: F7 L% L* M2 M0 c101 230400bps
6 @; `5 c3 L4 H: P6 y! o% J; H! T! e: o; [
110 460800bps. |5 H/ n/ t3 i, A/ U1 @' G
  `4 l% j" S, o( z! D4 |/ _
111 921600bps5 s! p. D5 k9 b2 E& Z

6 Y" u" Z; O0 J+ L* Q. Q/ U/ ]& ^) o# D1 G* t
1.2Uart_Byte_Tx

$ U1 v" o2 C: J8 T, i$ Z
Uart_Byte_Tx字节发送模块该模块在波特率时钟的节拍下,依UART通信协议发送一个完整的字节的数据。当一个字节发送完毕后,Tx_Done产生一个高脉冲信号,以告知其它模块或逻辑一个字节的数据已经传输完成,可以开始下一个字节的发送了。发送一个字节数据实现代码如下:
, N3 X. V& |; u/ x1 a. X
: p# v5 k. ~/ \5 k" b
33  /*计数波特率时钟,11个波特率时钟为一次完整的数据发送过程*/    
* p$ c8 m+ ~2 w, A0 B" y  e- Z1 w2 o5 j3 i
34      always@(posedge Clk or negedge Rst_n)
: e% h2 G& }* X' H/ N) Z
9 P  ^2 H6 b+ r. p+ i35      if(!Rst_n)( @- A  r3 G, r- c* q8 F) o3 t
9 }0 a  i0 r8 \5 ~& F" `; b
36          Bps_Clk_Cnt <= 4'b0;$ j, ]9 Y, z( c; @- H
. I7 z* Q) ~* g* F" z
37      else if(Bps_Clk_Cnt == 4'd11)
8 g! P( C# \8 o/ M- ?" s4 o+ E, X# V- {
38          Bps_Clk_Cnt <= 4'b0;# d; t$ I) U$ I/ y2 H/ Q
+ J$ t  a5 I0 L
39      else if(Bps_Clk)
4 M( ~- A) e' o9 {& \! \) Z' }* z6 A
9 N: K( r% [/ g# B) `40          Bps_Clk_Cnt <= Bps_Clk_Cnt + 1'b1;% r+ e! h; D' g3 J, z

$ b$ F. }. f: r41      else
* w. {/ `" I0 X& v1 Z1 v( V. u7 ?& i# B
42          Bps_Clk_Cnt <= Bps_Clk_Cnt;
# y5 S* ]: h( x$ v: Q) }
9 i$ l3 Z6 h) M9 _: V. G43
( J2 @& j" ~5 Y6 p0 L
8 W7 w2 F6 ~& x; A5 h2 N7 }44  /*生成数据发送完成标志信号*/        
0 Q0 Z; m& t2 P) _9 x- q4 R  i" J
4 G& p  G9 [+ P- I0 s7 }45      always@(posedge Clk or negedge Rst_n)
: m# t1 M" i; ?" R+ [' }" x& S: v# ?
46      if(!Rst_n)3 U2 r) [1 a8 d! {" _
: S$ k6 }" z* x  }6 A& Z/ u8 J
47          Tx_Done <= 1'b0;
, m  S) ~2 G9 I  A6 \6 T' n  |( N7 n6 ?4 {
48      else if(Bps_Clk_Cnt == 4'd11)
" f  k9 @4 }' _3 A9 X( k. y4 Q2 L( E4 |
49          Tx_Done <= 1'b1;
+ N. W2 i% M$ T, y% q* @( o6 b( [& s1 B9 M' m. Q% t
50      else. v) Q5 ?& X# h, ^9 I7 ~, @

  d  `1 ~3 R% H2 j# R' v1 @51          Tx_Done <= 1'b0;( A  ]( T0 \% L1 Q) f

4 D  P. A* B, X# E3 g52
/ Q7 u: t! T3 y( T# V1 I% ?6 d( U$ p; X- Z9 Y
53  /*在开始发送起始位的时候就读取并寄存Data_Byte,以免Data_Byte变化导致数据的丢失*/      
, l9 ?7 I) B  ?; r2 ?9 x# |4 O1 e# c0 z0 n" L
54      always@(posedge Clk or negedge Rst_n)
& L% @% G2 ?' R9 @8 B2 `& W) O; Z: k) y
55      if(!Rst_n)( x, n7 `. `3 ]3 S
9 i+ `1 z8 U" p4 }& M: I* P
56          Data = 8'd0;
/ p3 F) i: s9 R0 Q; I
* W/ g4 Z+ J" B. J8 ~+ [( Y57      else if(Bps_Clk & Bps_Clk_Cnt == 4'd1)9 B/ m' l9 e" b( _  C

8 O2 C. P- K$ `0 h' X0 z9 C, e58          Data <= Data_Byte;9 }9 q/ ?/ \1 o& s' r+ b
4 [0 {; W3 e, A1 T. A# D; N$ [
59      else
( x5 ^/ Q9 T- l- |6 E& D" @5 x" q8 r" P, Z  A  j3 K1 ?- U# w* B9 O
60          Data <= Data;. S0 _  r$ p2 g
8 B! L$ \' f; s" k2 L
61
) }* F& o) W- P9 w' s3 w
+ {7 s0 L* Z( Y6 `6 @62  /*发送数据序列机*/      
" `% i* ?- k1 r- Z; c  [' c
$ w: l8 T2 W9 f1 C% @63      always@(posedge Clk or negedge Rst_n); `0 W, V5 V7 w- J9 u/ C
) p( F2 Y$ a+ [% m5 N* G6 a
64      if(!Rst_n)  1 I4 g* P! P. V8 Y1 t, A* q; Y, Y
( B3 R8 H9 L. K! e* \
65          Rs232_Tx <= 1'b1;
5 C! q/ @  \; G
, S! y1 J3 \( Y4 K7 i( @) j) e' Q66      else begin
. \1 z: w( _6 V0 e  L
: _% [2 a' J8 g& E0 @67          case(Bps_Clk_Cnt)
4 k, z0 x. l  T5 r4 t% z% w$ o" b. K$ G0 _0 i# C' g/ F
68              4'd1: Rs232_Tx <= 1'b0;
9 ~3 R6 i0 ^. Y7 o5 x4 r
9 e/ H7 c. _- M; A. m69              4'd2: Rs232_Tx <= Data[0];+ j. k2 m( D4 a

% P8 K, Q+ e) r; w9 e2 w70              4'd3: Rs232_Tx <= Data[1];
' w4 F9 `* [# _- B% m: R
  X! P( i0 P* x) k' H71              4'd4: Rs232_Tx <= Data[2];  6 q: P" o, d) m) \# \8 g1 c

' d8 T$ t9 B- A72              4'd5: Rs232_Tx <= Data[3];. w) r1 @0 L6 l( y

! V% R  `, W9 g0 L2 I$ s73              4'd6: Rs232_Tx <= Data[4];
2 y6 H/ H! M0 t0 P5 S
% s" ^2 S- m; k! U- w74              4'd7: Rs232_Tx <= Data[5];+ Y$ w* z5 ]. [, u& }
$ c% L. N9 ^  ^) o* {0 r0 `
75              4'd8: Rs232_Tx <= Data[6];
6 d9 G( N  _+ i4 E
* L2 ~# Z! p# u% t/ u# N76              4'd9: Rs232_Tx <= Data[7];1 r$ K3 S1 V  v* T: @( C

# M. A  E" r8 S7 R77              4'd10: Rs232_Tx <= 1'b1;
# w+ K0 I: t$ W) A3 Y( f; l/ B) Z3 n$ l& F' b  Q
78              default:Rs232_Tx <= 1'b1;4 @" r! [& e, R$ i1 `

& W% A0 _$ y+ i$ w- U. Z: X! A$ ?79          endcase
1 e. i- k) K1 D9 |: \9 K. @" {" O+ a: W# U" g" o
80      end
, L' }* h/ ~% U2 @9 ^* s  A) ]4 w1 _# V2 ]$ u; L
2 u, y5 |, d/ S, R2 d% G
UART协议中,一个完整的字节包括一位起始8数据位一位停止位总共十位数据,那么,要完整的实现这十位数据的发送,就需要11波特率时钟脉冲,如下所示
% I: `2 }" q1 [- t. ?- {
* m% x' a1 D! r. f0 |/ [: }: V0 [0 x! o
" M8 V! u, L; b+ @! b, E/ _

: ~0 F- y6 p0 D0 r
# c: B- O; b. e
BPS_CLK信号的第一个上升沿到来时,字节发送模块开始发送起始位,接下来的29上升沿,发送8数据位,第10上升沿到第11个上升沿为停止位的发送。

- u3 \) E" d. G0 z
单个串口接收模块中实现串口数据接收的主要代码如下所示:
025     always @ (posedge Clk or negedge Rst_n)
026     if(!Rst_n) begin
027         Rs232_Rx0 <= 1'b0;
028         Rs232_Rx1 <= 1'b0;
029         Rs232_Rx2 <= 1'b0;
030         Rs232_Rx3 <= 1'b0;
031     end
032     else begin
033         Rs232_Rx0 <= Rs232_Rx;
034         Rs232_Rx1 <= Rs232_Rx0;
035         Rs232_Rx2 <= Rs232_Rx1;
036         Rs232_Rx3 <= Rs232_Rx2;
037     end
038     
039     wire neg_Rs232_Rx= Rs232_Rx3 & Rs232_Rx2 & ~Rs232_Rx1 & ~Rs232_Rx0;
040     
041     assign Byte_En = neg_Rs232_Rx;
042
043 /*----------计数采样时钟--------------*/
044 /*9倍波特率采样时钟,故一个完整的接收过程有90个波特率时钟*/
045     reg[6:0]Sample_Clk_Cnt;
046     always @ (posedge Clk or negedge Rst_n)
047     if(!Rst_n)
048         Sample_Clk_Cnt <= 7'd0;
049     else if(Sample_Clk)begin
050         if(Sample_Clk_Cnt == 7'd89)
051             Sample_Clk_Cnt <= 7'd0;
052         else
053             Sample_Clk_Cnt <= Sample_Clk_Cnt + 1'b1;
054     end
055     else
056         Sample_Clk_Cnt <= Sample_Clk_Cnt;
057
058     reg [1:0]Start_Bit; /*起始位,这里虽然定义,但并未使用该位来判断接收数据的正确性,即默认接收都是成功的*/
059     reg [1:0]Stop_Bit;  /*停止位,这里虽然定义,但并未使用该位来判断接收数据的正确性,即默认接收都是成功的*/
060     reg [1:0] Data_Tmp[7:0];/*此部分较为复杂,请参看说明文档中相关解释*/
061     
062     always @ (posedge Clk or negedge Rst_n)
063     if(!Rst_n)begin
064         Data_Tmp[0] <= 2'd0;
065         Data_Tmp[1] <= 2'd0;
066         Data_Tmp[2] <= 2'd0;
067         Data_Tmp[3] <= 2'd0;
068         Data_Tmp[4] <= 2'd0;
069         Data_Tmp[5] <= 2'd0;
070         Data_Tmp[6] <= 2'd0;
071         Data_Tmp[7] <= 2'd0;
072         Start_Bit <= 2'd0;
073         Stop_Bit <= 2'd0;      
074     end
075     else if(Sample_Clk)begin
076         case(Sample_Clk_Cnt)
077             7'd0:
078                 begin
079                     Data_Tmp[0] <= 2'd0;
080                     Data_Tmp[1] <= 2'd0;
081                     Data_Tmp[2] <= 2'd0;
082                     Data_Tmp[3] <= 2'd0;
083                     Data_Tmp[4] <= 2'd0;
084                     Data_Tmp[5] <= 2'd0;
085                     Data_Tmp[6] <= 2'd0;
086                     Data_Tmp[7] <= 2'd0;
087                     Start_Bit <= 2'd0;
088                     Stop_Bit <= 2'd0;   
089                 end
090             7'd3,7'd4,7'd5: Start_Bit <= Start_Bit + Rs232_Rx;
091             7'd12,7'd13,7'd14ata_Tmp[0] <= Data_Tmp[0] + Rs232_Rx;
092             7'd21,7'd22,7'd23ata_Tmp[1] <= Data_Tmp[1] + Rs232_Rx;
093             7'd30,7'd31,7'd32ata_Tmp[2] <= Data_Tmp[2] + Rs232_Rx;
094             7'd39,7'd40,7'd41:Data_Tmp[3] <= Data_Tmp[3] + Rs232_Rx;
095             7'd48,7'd49,7'd50:Data_Tmp[4] <= Data_Tmp[4] + Rs232_Rx;
096             7'd57,7'd58,7'd59:Data_Tmp[5] <= Data_Tmp[5] + Rs232_Rx;   
097             7'd66,7'd67,7'd68:Data_Tmp[6] <= Data_Tmp[6] + Rs232_Rx;
098             7'd75,7'd76,7'd77:Data_Tmp[7] <= Data_Tmp[7] + Rs232_Rx;   
099             7'd84,7'd85,7'd86:Stop_Bit <= Stop_Bit + Rs232_Rx;
100             default:;
101         endcase
102     end
103     else ;
根据串口发送协议,一个字节的数据传输是以一个波特率周期的低电平作为起始位的,因此,成功接收UART串口数据的核心就是准确检测起始位。由于外部串口发送过来的数据与接收系统不在同一个时钟域,因此不能直接使用该信号的下降沿来作为检测标志,我们需要在fpga中,采用专用的边沿检测电路来实现,第25至37通过四个移位寄存器,存储连续四个时钟上升沿时外部发送数据线的状态,第39通过比较前两个时钟时数据线的状态与后两个时钟时数据线的状态,来得到该数据线的准确下降沿,以此保证起始位的准确检测。
在简单的串口接收中,我们通常选取一位数据的中间时刻进行采样,因为此时数据最稳定,但是在工业环境中,存在着各种干扰,在干扰存在的情况下,如果采用传统的中间时刻采样一次的方式,采样结果就有可能受到干扰而出错。为了滤除这种干扰,这里采用多次采样求概率的方式。如下图,将一位数据平均分成9时间段,对位于中间的三个时间段进行采样。然后对三个采样结果进行统计判断,如果某种电平状态在三次采样结果中占到了两次及以上,则可以判定此电平状态即为正确的数据电平。例如456时刻采样结果分别为110那么就取此位解码结果为1否则,若三次采样结果为010则解码结果就为0
因为采样一位需要9时钟上升沿,因此,采样一个完整的数据需要10*9,即90时钟上升沿,这里,采样时钟为波特率时钟的9。产生采样时钟的部分代码如下所示:
089 /*-------波特率时钟生成定时器--------------*/
090     always@(posedge Clk or negedge Rst_n)
091     if(!Rst_n)
092         Count <= 10'd0;
093     else if(BPS_EN == 1'b0)
094         Count <= 10'd0;
095     else begin
096         if(Count == BPS_PARA)
097             Count <= 10'd0;
098         else
099             Count <= Count + 1'b1;
100     end
101     
102 //=====================================================
103 /*输出数据接收采样时钟*/
104     always @(posedge Clk or negedge Rst_n)
105     if(!Rst_n)
106         Sample_Clk <= 1'b0;
107     else if(Count== 1)
108         Sample_Clk <= 1'b1;
109     else
110         Sample_Clk <= 1'b0;
' p/ K2 p/ X/ P
这里,BPS_PARA的计算原理和前面Tx_Bps_Gen模块中的BPS_PARA的计算原理一致,不过这里,因为采样时钟为波特率时钟的9,所以,BPS_PARA为Tx_Bps_Gen模块中的BPS_PARA1/9。计算BPS_PARA的相关代码如下:
018     parameter system_clk = 50_000_000;  /*输入时钟频率设定,默认50M*/
019
020 /*根据输入时钟频率计算生成各波特率时分频计数器的计数最大值*/   
021     localparam bps9600 = system_clk/9600/9 - 1;
022     localparam bps19200 = system_clk/19200/9 - 1;
023     localparam bps38400 = system_clk/38400/9 - 1;
024     localparam bps57600 = system_clk/57600/9 - 1;
025     localparam bps115200 = system_clk/115200/9 - 1;
026     localparam bps230400 = system_clk/230400/9 - 1;
027     localparam bps460800 = system_clk/460800/9 - 1;
028     localparam bps921600 = system_clk/921600/9 - 1;     
029     
030     reg [31:0]BPS_PARA;/*波特率分频计数器的计数最大值*/
031
032     always@(posedge Clk or negedge Rst_n)
033     if(!Rst_n)begin
034         BPS_PARA <= bps9600;    /*复位时波特率默认为9600bps*/
035     end
036     else begin
037         case(Baud_Set)  /*根据波特率控制信号选择不同的波特率计数器计数最大值*/
038             3'd0: BPS_PARA <= bps9600;
039             3'd1: BPS_PARA <= bps19200;
040             3'd2: BPS_PARA <= bps38400;
041             3'd3: BPS_PARA <= bps57600;
042             3'd4: BPS_PARA <= bps115200;
043             3'd5: BPS_PARA <= bps230400;
044             3'd6: BPS_PARA <= bps460800;
045             3'd7: BPS_PARA <= bps921600;            
046             default: BPS_PARA <= bps9600;/*异常情况,恢复到9600的波特率*/
047         endcase
048     end
: n! v* `& t! M; D6 Z) {
小梅哥
2015年4月8日 于至芯科技
+ D( L# Q" Q- z

6 _  a& Y" H* n6 x7 w8 |' a1 w0 l! ~* [1 c/ ?% m2 V
( ]+ S( W4 o! [3 ?  q  M

4 F# N6 F  Q! @: V+ Y: e7 e, }2 p. I; B' \, o7 L0 J: x5 @
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-7-30 12:20 , Processed in 0.171875 second(s), 23 queries , Gzip On.

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

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

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