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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

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

% n5 ?- y% D; o+ V' O
串口发送接收模块设计代码分析) O/ J2 {* P: V2 ~# f
1.1Tx_Bps_Gen
7 e; N' H# R; ]
Tx_Bps_Gen发送波特率生成模块,每当Byte_En信号到来时,即开始产生发送一个完整字节的数据需要的完整波特率时钟信号
; z+ ~0 l5 Q9 x! N( e本设计,波特率支持9600bps921600bps例如需要产生的波特率时钟为9600bps波特率时钟频率为9600Hz周期104.17us生成9600Hz波特率时钟的核心思想就是对系统时钟进行计数,这里设定系统时钟为50MHz,则一个时钟的周期为20ns,我们只需要对系统时钟计数5208每计数5208产生一个时钟周期的高电平脉冲,即可实现生成9600Hz波特率时钟的功能。相应代码如下所示:' x. s% ~! F1 ^% ^7 Q6 `6 _  v
* G) w# Z+ B5 \  J3 a
018     parameter system_clk = 50_000_000; /*输入时钟频率设定,默认50M*/* y: H" [8 p( @' K! l, j, x6 r  {! S

5 I* x4 I9 X' Q  }5 m* @. G& Z019& Y, K3 r( H  |* X4 r, v
9 |) {6 _  O* Y3 A- I, o; m
020 /*根据输入时钟频率计算生成各波特率时分频计数器的计数最大值*/        8 n( r, G) B& ]/ {0 u
. X- N: @# U. S" @
021     localparam bps9600 = system_clk/9600 - 1;. f$ f0 ^; n* Q" f+ V* C. G

) d" `7 {0 x( A( ^7 w( w+ w022     localparam bps19200 = system_clk/19200 - 1;
( l+ o3 J# f+ q' X% Q4 K1 B" [$ n7 ~/ R
023     localparam bps38400 = system_clk/38400 - 1;7 M- r( K  T8 G8 E+ e6 Z
, o) v! Y6 z' W$ @1 c3 V7 g
024     localparam bps57600 = system_clk/57600 - 1;2 Q+ ]+ ^3 h, M" p! F# H

: ~1 O$ F/ [  M" A+ q7 U' @025     localparam bps115200 = system_clk/115200 - 1;
0 }+ k% r: Z1 o) k+ {
+ w' i( I3 m% B& F6 |. F026     localparam bps230400 = system_clk/230400 - 1;1 [( Q! m% L/ S& o; _* O* {, x
5 O3 J$ ~" _+ l7 R- E* V' w
027     localparam bps460800 = system_clk/460800 - 1;
2 B. L: @+ s, y
5 D0 `4 e9 s9 E+ _" L0 p028     localparam bps921600 = system_clk/921600 - 1;       5 }/ T# r* D- T( l3 f+ L
: D3 q, F; ^$ i
029     
0 {- z6 J7 w$ A! Z, h: s3 s$ ]6 I# N# w; m; z$ P
030     reg [31:0]BPS_PARA;/*波特率分频计数器的计数最大值*/# Z) q% a3 \" [" g2 v6 l& G' \
$ ~- U( D/ o6 ]+ b# F' `
031
: H+ q0 k" A. k" Y
. g- e0 |/ v4 W9 r: d6 [5 g032     always@(posedge Clk or negedge Rst_n)! d; @9 R- x" z7 s

2 h4 Y7 W; _2 v/ R033     if(!Rst_n)begin; K; j& ~5 [, p- |/ G( B9 v8 a

# n) v4 c( e  g0 L3 J) H034         BPS_PARA <= bps9600;/*复位时波特率默认为9600bps*/
) q8 `. ?1 {) E5 d# j# C' c/ a7 Y' F# [
035     end
$ f" u$ ^! Y) t+ T8 O9 z
1 g8 y2 [$ u  A- m; j, ?) v3 q036     else begin5 @3 w6 I6 g* `0 Q4 K

: G% n; O% S! M( X( r" b: L037         case(Baud_Set)/*根据波特率控制信号选择不同的波特率计数器计数最大值*/5 O; t8 X; y8 _: @2 @3 x

% n5 C( d; h! C5 h' R/ s2 G# n# y038             3'd0: BPS_PARA <= bps9600;
# y9 V- s6 h, h. Y& H1 g! w$ t7 N4 O/ g+ [, a) U" h' q2 x
039             3'd1: BPS_PARA <= bps19200;" l  b+ O) M% z8 m$ q/ S
2 M8 n. A9 E0 ]: b- G
040             3'd2: BPS_PARA <= bps38400;
& h8 J9 N0 w# w2 l9 Y& k7 M/ L0 v1 u7 Z) q7 D  e, H
041             3'd3: BPS_PARA <= bps57600;4 z- Y, S' K2 a* I( s
! T5 u3 b7 M0 s/ m  H9 _! _
042             3'd4: BPS_PARA <= bps115200;
7 Z. h7 r! {) j
- U4 v" E( _& \$ v6 I$ q  e3 U043             3'd5: BPS_PARA <= bps230400;9 y+ G, G: |9 Z4 e" _8 @. I; A' v$ Z
( ?8 h" |8 Y. Y' R/ Z$ p, k' `& r' ]/ v
044             3'd6: BPS_PARA <= bps460800;
. b; r5 X+ [4 g; _% H: o& Q1 {: g- I  P) L5 }7 A
045             3'd7: BPS_PARA <= bps921600;            % o6 k9 y& ?7 a3 e
. g5 O# o8 j- \1 {
046             default: BPS_PARA <= bps9600;
0 Z/ u6 ^+ N: L* N3 F9 W# u
* `: L4 I% p: }$ X1 \( }047         endcase
7 _  W6 v' I. f- |  a1 _6 k0 I6 Q' T- A9 U" `
048     end
# ]% M: z, L+ X9 N/ p3 y6 i$ O) X2 H& Q( W
049     - Z% M6 \5 Y  ^/ }9 |+ a+ B
' {7 Z" U+ S# u: f
050 //=========================================================
: p( R# ?- ]6 h* r* p1 g
9 s- t8 s* ]- D* A# B051     reg[12:0]Count;# |$ _1 J$ l3 x+ x
/ _) t& H8 S0 d2 ~$ C
052     
4 j- t# Y- f. `
$ F$ ^9 }5 s* ~. C8 U- G5 ^) [053     reg n_state;4 f9 ^2 A6 @" q7 d- s8 Y7 t
: m7 O* \" s/ f7 b8 m4 E+ ^
054     localparam IDEL_1 = 1'b0,8 H2 `: ^( Z5 _

4 M) s- B" e* C0 ~055                   SEND   = 1'b1;9 L& S( I3 E. s9 b
' S$ B' p9 N5 ]% A/ D# J
056                   " V. {' H0 C- i  V( e

+ o8 [  r  E) V- q, ]" K& `0 \/ w057     reg BPS_EN;
  ~$ z& x6 G5 z
8 u3 f$ O. o3 w; F0 R5 O4 W058     2 N# H7 D! \/ M! M

, c6 \3 g* \9 N* K059 /*-------波特率时钟生成控制逻辑--------------*/  + ?0 }$ w+ d! i  s* K! J
3 A' s; Q( n7 n, P2 j& ?* k! A
060     always@(posedge Clk or negedge Rst_n)
7 s  W3 j) T! ~3 H  y
& N  e' D7 G* R7 @; @2 c" ?: t061     if(!Rst_n)begin
! x5 f! s' h0 V/ t" B/ F/ T. A7 j" J. M1 Q
062         BPS_EN <= 1'b0;! k! u6 z  v% ^% T
* C4 G4 Z$ Y" |9 {4 O7 w
063         n_state <= IDEL_1;
0 X8 X$ O+ a% j
- N' U$ Z4 g+ Q$ z064     end0 P5 X4 R7 P* F7 @5 p* N

9 J/ {- S7 N. o) V065     else begin8 K# [2 j% l& S  D
; u+ a# f: {- s
066         case(n_state)- c& o! N& I, @5 C, [

/ b; j: h  l, Z067             IDEL_1:
, }  @, R2 ~6 H3 \" n2 e& {2 k$ X: a  T! \$ x; R/ f, L
068                 if(Byte_En)begin/*检测到字节发送使能信号,则启动波特率生成进程,同时进入发送状态*/" Q% g# J/ q, A0 O& I7 o' K* W

& F+ I- i! g" D" b! k! x069                     BPS_EN <= 1'b1;+ K" M( a& Z  ?" |& O) w. [

/ W* W# G5 Y" C( [7 }$ ]070                     n_state <= SEND;
0 v% M& \% C+ Q. c! I( l: @9 ]6 X8 m4 w/ G! L& o" T% D( Q
071                 end6 z9 a* h/ a- L3 p6 x$ N

5 K% H; {' ]" G) [072                 else begin" I& t' F, Q, G" f

6 X! M9 `1 @' o- q/ E6 k073                     n_state <= IDEL_1;) l7 t5 V/ [, G* j1 N5 Z
& y- z, l2 ?8 N6 h6 A' }1 r
074                     BPS_EN <= 1'b0;
5 a: ?8 L1 p+ w0 G, R, ?6 f5 f2 \3 }8 n4 `3 m4 F
075                 end
) `! O* g. v- z, N, }. l7 `) v+ [2 f, i+ D
076             SEND:1 G5 R$ C+ U* i" r
: j7 V) d; d' J% c" Y
077                 if(Tx_Done == 1)begin/*发送完成,关闭波特率生成进程,回到空闲状态*/
0 X& J7 s3 w, ]: o9 C3 b3 q5 `9 s; I# E6 a7 }; }) }, x
078                     BPS_EN <= 1'b0;
# m# [. c: P" u+ L" d* f
' `1 H2 r8 {* Y8 E/ y6 Z! u  p! i079                     n_state <= IDEL_1;! R- P5 A4 [% |1 ]: I; _
5 w. B: n7 p! o5 b6 W( l5 s$ z
080                 end- E, I6 }% C, g; R! i
2 y5 p9 [- J) V- n5 i8 L( _8 K
081                 else begin
, w. b; A9 W* W8 F1 D) I* J* ~# n" L- f2 v- k
082                     n_state <= SEND;
6 {4 ]4 w& r$ U% |3 i1 w7 L: L1 j. [: Q
083                     BPS_EN <= 1'b1;6 O# B+ m$ W& }3 `) X- g
; \3 i  X; g9 o; C, Y7 r
084                 end0 `7 T  A  V; f- }

' s# g4 ^2 q8 S: s085             default:n_state <= IDEL_1;6 I6 J5 M5 l9 l: t+ I0 X4 e( H$ m

4 C4 m( p1 z( P3 _$ j2 e086         endcase4 g3 C% y# g% W
+ ?2 m4 f3 C$ Y  f- w" k+ h% B
087     end- r' `* d4 @1 p

+ h5 x6 l& ?1 E! K. U/ o9 c' o088
: B; `7 f1 v( s: ^" L' T( O2 G, w6 [  P
089 /*-------波特率时钟生成定时器--------------*/
- ]) H9 T/ j& q% K
$ {; I$ U4 V, ]8 E& h090     always@(posedge Clk or negedge Rst_n): h8 w- f+ A: v& K
6 k6 F7 M  m  n3 ^) L
091     if(!Rst_n)
6 S8 q% H* \' f. r: \4 n& q6 \3 F/ P, }
092         Count <= 13'd0; $ J, s6 k& ~* G7 e; L. v. M

1 f' Y0 n+ p; Z6 E+ F( m, p093     else if(BPS_EN == 1'b0)1 |/ f4 H! H* p
1 I# o& o. v5 o& C5 I( U
094         Count <= 13'd0;
/ U2 o4 T% K- S& g9 y7 q5 S% L% _' w9 d* W
095     else begin1 i3 {3 P5 `/ ?# u

  v9 O- m2 I- q6 P: ~* |4 r096         if(Count == BPS_PARA)
& ~: l4 I1 m' ^! V( i* k  I. c( u; T- O& P. V( e# m! W+ F8 y, ~
097             Count <= 13'd0;/ m- Q3 `/ b& m$ |" m

) G1 f& {  E3 A' I6 h098         else 8 U3 d* u5 L9 q1 c
* m2 C" F6 h' M! e  G3 g
099             Count <= Count + 1'b1;
$ s) R! U; v2 V/ k2 a, I! |5 Z, E! J; E" |9 T
100     end
% W* @3 n- \/ j- T/ Z8 D  x. Q& j0 `/ R2 K: a
101     
& o+ {; d+ i! G4 S6 [& {1 z+ D% J8 y2 o( B" e" J: |7 A
102 /*输出数据接收采样时钟*/  - R  C4 e& t$ c2 T; i# l

5 t/ h/ r2 X) G) \" M4 l: P103 //-----------------------------------------------
5 h4 b/ g7 q" a4 m) D/ l
$ I8 J% Q# v: n* s104     always @(posedge Clk or negedge Rst_n)
6 q; t5 B9 p9 [: u; a$ d7 w8 U
1 }9 E. Q: O  a105     if(!Rst_n)
: o1 ]( a% G/ Q" w6 l; B9 J5 M9 s, `% `  G7 @7 ~- ]5 e
106         Bps_Clk <= 1'b0;, J6 ~$ [$ g3 @1 s) s
5 s/ e, r+ ?- P9 D( N0 a
107     else if(Count== 1)
' f% H: L* v# r5 r; n
: r. K  u9 }) c! U5 n! l2 M- S7 g108         Bps_Clk <= 1'b1;2 Q+ Z5 c5 b0 Q2 X4 X
2 @3 p8 ]4 h% x6 `! r+ c  }9 a
109     else
1 n8 l, e( a/ Q0 @. ?5 Q1 d3 f  ^8 Y# C8 ^
110         Bps_Clk <= 1'b0;- S7 Z! n2 O+ v( v7 U

) ~; P& j1 S9 s  D6 U3 o
* @; e+ [5 c8 g0 d8 k' C
18行“parameter system_clk = 50_000_000;,这里用一个全局参数定义了系统时钟,暂时设定为50M,可根据实际使用板卡上的工作时钟进行修改。
9 t, N' L; u. ~& f# y" y所谓波特率生成,就是用一个定时器来定时,产生频率与对应波特率时钟频率相同的时钟信号。例如,我们使用波特率为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为波特率定时器定时值的计算部分2 b, y6 w5 P' G, a! h
为了能够通过外部控制波特率,设计中使用了一个3的波特率选择端口Baud_Set。通过此端口不同的,就能选择不同的波特率,此端口控制不同波特率的原理很简单,就是一个多路选择器,32至第48即为此多路选择器的控制代码, Baud_Set波特率的对应关系如下:% F$ c/ S: G6 R( A0 Q4 e% h# K" k% Q

# A0 q- g+ s; ^( b- S+ L; i" C1 T000 9600bps
8 k0 N: l& X) [- X& R
9 i2 _: k% n6 U; u001 19200bps;
- F- d* U% Z$ A/ w) B& q  M1 H6 s0 f9 t$ t; d
010 38400bps;4 S0 y% U9 ?' [+ V$ G; n
$ i' \- b/ z; q: F+ G
011 57600bps
6 N  }" h! R' Q* ]8 Q5 i
  o/ ^8 A3 X. |2 R! N100 115200bps
# ?* z/ e) V9 q& y
( r9 e1 p, L2 q: K4 M: c1 Q101 230400bps
9 m% q! B6 v0 N7 a& o2 \; K/ p4 W# Z! n  Z9 ^  |1 g, @
110 460800bps8 u2 A$ P+ |* M+ J/ f  X  p

+ f8 Q0 z8 e( J/ a; e, E111 921600bps
( M+ i" \1 }1 h! D1 ^+ ^
. F) W" a2 E8 O/ D3 c
# v) ?/ M; ~% t: G1.2Uart_Byte_Tx

, c9 F+ N& q# B2 m' N
Uart_Byte_Tx字节发送模块该模块在波特率时钟的节拍下,依UART通信协议发送一个完整的字节的数据。当一个字节发送完毕后,Tx_Done产生一个高脉冲信号,以告知其它模块或逻辑一个字节的数据已经传输完成,可以开始下一个字节的发送了。发送一个字节数据实现代码如下:# v: m, y7 s5 Z9 \" R
! w: O7 n& q5 V8 S. s! A
33  /*计数波特率时钟,11个波特率时钟为一次完整的数据发送过程*/    
4 v/ ^2 E' B; S5 P9 B% S
- s  z  ]3 n- K' m/ d. V34      always@(posedge Clk or negedge Rst_n)
4 X2 y4 B0 a7 R4 _( H
' {; k, z. z' X% h  w6 Q0 _35      if(!Rst_n)
! u+ f! A( ?  R
( m' y! J: ?6 \' k( ~& p36          Bps_Clk_Cnt <= 4'b0;
; \) L% v3 r4 N  A
0 o  d8 c" N5 j7 H37      else if(Bps_Clk_Cnt == 4'd11)
$ T/ L4 d! }: H2 Q6 Y' K$ o0 j4 ~& u6 ^3 _" I
38          Bps_Clk_Cnt <= 4'b0;
. l7 V* j7 p2 _4 z/ L, ]8 H) ~' L  e# N  }
39      else if(Bps_Clk); Q6 s/ D2 C1 F; a: u2 n
+ E0 Z! z: y0 Y; M
40          Bps_Clk_Cnt <= Bps_Clk_Cnt + 1'b1;9 j4 M. O1 B; B* _! j$ {3 E* \$ @

" Z1 G5 g/ t( m/ Y% x41      else
% `2 Z* @% C, i/ O
' X' O) ~6 f4 }& k) W" N( d42          Bps_Clk_Cnt <= Bps_Clk_Cnt;( [- ]3 X8 |' _& D7 c) I
/ ~; H8 s0 y& {
43
% s4 Q) i; ^4 ~# b! D1 v9 v# ^" ]) Y
44  /*生成数据发送完成标志信号*/        / e) N  B: L& P/ [% F1 [7 c9 O" p
7 X: ^. ^% L1 A2 B! T! ~4 `, O
45      always@(posedge Clk or negedge Rst_n)
# `6 T: O! h) d3 a0 i1 }' i) f
7 {8 J3 G4 D3 I46      if(!Rst_n)" h5 a4 B; Q; E
. @, _1 t" _6 I
47          Tx_Done <= 1'b0;* p" r) j. \. s; j- C
0 {, ^9 [# `1 d/ L# H$ E% f/ R
48      else if(Bps_Clk_Cnt == 4'd11)
: k8 P7 x' Z8 M& Z% C
; `2 w4 c; J3 \/ l49          Tx_Done <= 1'b1;
$ N- p7 n  X0 {
/ C' V- t4 e6 j# p" R50      else4 \2 d1 ]$ [& k* R' I' w, r
3 C$ [: |% `$ N" x0 v
51          Tx_Done <= 1'b0;
2 d3 f. |4 F6 Y1 T. N/ h& ]# M3 {! }+ y
52
1 k. E0 m- f9 A2 w  |4 }# u) p5 w0 m
53  /*在开始发送起始位的时候就读取并寄存Data_Byte,以免Data_Byte变化导致数据的丢失*/      
( r6 k! A9 G! D/ y2 y7 g, C  Z2 G
7 D0 ]# M  L' A- `, [54      always@(posedge Clk or negedge Rst_n)8 z6 A! O+ T" i2 @
; B( p+ O2 W! W0 m2 d, G
55      if(!Rst_n)" _# Y& J9 h8 N' P3 \
2 W/ T. a7 X( D) g
56          Data = 8'd0;" M( M9 g3 i3 M" X) c% i4 p
& Q" K) X( U; e' d
57      else if(Bps_Clk & Bps_Clk_Cnt == 4'd1)5 z: n5 ]* Q  A8 B5 _
& Z: X! {4 r5 t2 @* S5 n
58          Data <= Data_Byte;! P! x: I3 H, c. |" D% b( d
" _" m5 K$ n" u6 c( k% w9 t
59      else+ \. \( v4 I: ^4 S; [
' S+ @4 q  [! K6 ~" K1 Z% C
60          Data <= Data;
7 ~6 A# K9 G" Z( ^! i5 M
& d& O7 s! U+ ~9 F% d61) z, U7 |' }. M/ }8 Z' a% {: o
6 }8 Q/ Z1 R5 @
62  /*发送数据序列机*/      
, N$ P1 S, y8 o. W. Y8 d5 l+ p: A# n+ W
63      always@(posedge Clk or negedge Rst_n)
+ D; D- |3 _- G% Z# M) a
0 J" x6 g0 b+ z: }5 w2 y64      if(!Rst_n)    V  N4 Z, a6 c. N4 K* E: K
3 L3 e2 p1 r1 L* |( o( A
65          Rs232_Tx <= 1'b1;
& \( ~3 Y% B8 S- L: @8 f
, x9 Q. Y+ R6 q6 H/ Z66      else begin
8 O) ]! ^' e- \0 y) B
$ h* A. W# Q. }& W67          case(Bps_Clk_Cnt)" f8 E4 f5 w2 g" b$ f0 d, p
( c1 m# R; q) j3 C: k1 [' ~
68              4'd1: Rs232_Tx <= 1'b0;, Z- s1 i9 y# \" J/ Y3 F) [1 u3 i

* \9 J, ?" m; N7 m, j4 t7 ^3 j$ I3 {# D$ _69              4'd2: Rs232_Tx <= Data[0];
/ [! l. H0 c. T* h0 }9 ]
+ l2 S# }: u! O+ \& U8 Q" d9 Z70              4'd3: Rs232_Tx <= Data[1];3 e: `& n1 c. f3 a0 \

+ s! z) z/ n7 A! Q0 Q71              4'd4: Rs232_Tx <= Data[2];  
, b8 I& c  C% N6 g
* I* T$ O; }6 M0 i$ [& r  r1 [8 _/ V72              4'd5: Rs232_Tx <= Data[3];# G% |9 _# U+ X1 {
2 k6 r6 ?: `& S- s; I) q% `
73              4'd6: Rs232_Tx <= Data[4];, h) j6 t" d  g

& B6 Q5 ^& v7 e74              4'd7: Rs232_Tx <= Data[5];
7 l9 `: O* o. ^% X3 ?1 y2 z! f8 V# v8 j2 @; a8 S
75              4'd8: Rs232_Tx <= Data[6];( V6 I! X8 X% J  |6 t

' C" ]& D" G% A2 ^+ j7 ?5 J76              4'd9: Rs232_Tx <= Data[7];9 f" ]6 K! E- ]' ^/ j8 _, a. V" }

5 d* b) \8 H6 `3 i77              4'd10: Rs232_Tx <= 1'b1;( b$ D+ o2 u/ O8 C0 ], u8 Z& P
6 X; F; s' [% g8 d- P2 a+ C8 E
78              default:Rs232_Tx <= 1'b1;- K% j! ^1 U5 B( P" {  V

& Z8 v, `" N2 \; F5 ~+ l' u79          endcase- N' _" w4 w& t, O

2 D- r! @$ `4 y- {& b80      end
; z0 R) @/ Y& o9 S, s& N7 g7 x. l8 u! w9 ]+ T, N! U

: B% f8 x7 m9 ]# l( i. X
UART协议中,一个完整的字节包括一位起始8数据位一位停止位总共十位数据,那么,要完整的实现这十位数据的发送,就需要11波特率时钟脉冲,如下所示) b3 |3 v5 u7 W& v, L9 y" G
0 q8 J7 C6 F8 v2 _: U* d
0 z8 v% w/ @: o/ k/ R& t( Q

! U% ]6 m3 X7 x( ^( U' D) y' u, Y  g0 o( B
BPS_CLK信号的第一个上升沿到来时,字节发送模块开始发送起始位,接下来的29上升沿,发送8数据位,第10上升沿到第11个上升沿为停止位的发送。
0 l0 k0 \* E6 V0 D5 _
单个串口接收模块中实现串口数据接收的主要代码如下所示:
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;

9 V5 [7 W$ y% h# u- o. [5 |
这里,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

0 U$ Z$ o2 ~! v0 K+ [
小梅哥
2015年4月8日 于至芯科技

+ t* R- n8 p- y
1 W, A/ C$ Q, s1 @1 a( K7 D$ m0 e+ |8 a4 z
" D7 t2 y- q& }2 P: x

; [# J4 _" d4 e% ?9 v# a% T
* z  I9 P& r8 y
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-10-9 11:00 , Processed in 0.187500 second(s), 23 queries , Gzip On.

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

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

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