待会儿再结合falsh写下,这个简单的传输不注意细节同样搞死人
实现功能:电脑通过串口调试助手传送数据,然后fpga将接受到的数据再传送回来显示到串口调试助手的窗口
UART帧结构:
1位起始位(0)
8位数据位(LSB在前)
1位停止位(1)
没有校验位,数据位长度可为其他
思路以及步骤:(详细写下,加深印象)
一。模块
A.uart_top 完成模块的例化以及模块间的连接
输入输出只有rxd和txd,clk,rst_n
B.baud波特率发生器,传送采用9600 bits/S,因为uart是异步收发,在接收端,就需要采用远高于(这个设计中采用16倍)发送波特率的时钟去对rxd不断采样,所以需要分频产生两个时钟。
分频系数(分频因子)的计算= clk/波特率-------发送器的时钟 t_clk
clk*16/波特率-----接收器的时钟 r_clk
小的误差可以忽略,所以可以都用简单的偶数分频而不必用奇数分频
C.receiver:接收器模块
input r_clk,rst_n,rxd ;
output [7:0] r_buf;//串转并用于暂存接受到的数据,然后送给发送器模块并转串去发送
output r_ready;接收完毕信号
为了避免毛刺,得到正确的每位数据,所以最好是在每位数据的中间对其进行采样,所以,分为几个状态:
1.start开始状态
监测rxd信号,如果发现其为低,就转到下一个状态去测中点,否则,继续在start状态,ready为0
2.center状态,到达中点
监测rxd状态为0,如果计数器cnt(r_clk下)满5,就可以跳到下一个wait状态再去计数(为了达到每个数据位的中点),同时将cnt置零。
注意:这里的计数器满5就跳套wait去完成计数16的计数器,是很有讲究的。。。按照通常的来想,首先发送1个t_clk周期的起始位0,然后接着是数据位,那么我要在数据位的中点采样,应该是在r_clk满7(0-7)的时候(因为是16倍的t_clk),然后再计数满15(0-15),就可以刚好到达第一个数据位的中点可以采样了,但是,需要考虑:
center状态和sample采样状态之间,相隔了两个状态也就是2个r_clk周期,所以真正采样的时候,其实已经计数到了7(就是已经满8个了),这时候刚好,同样,在下一个的wait状态也要这样考虑、
这个思想在很多地方都用到
首先,center状态和真正的采样状态
没满当然自加,循环与center
如果rxd为高,则返回到start状态
3.wait
前面已经监测到起始位的中点,然后这里再记满14就可以去采样了,为什么只到14,原因和前面的一样
if cnt=14,在这个情况下,如果rcnt(串转并用到的计数器)满8,则跳到最后一个停止状态,否则,则跳转到sample状态,
如果不满14,则cnt+1,状态一直在wait
4.sample
串转并,rcnt+1,状态跳回wait
5.stop
让ready有效,这个信号同时送到发送器transfer
D。发送器transfer模块
主要就是注意先要发送一位起始位,最后还要发送1位终止位
所以这里的t_buf[9:0]={1'b1,r_buf[7:0],1'b0},然后判断ready信号
如果ready信号为1,则拉高txd,cnt清零
否则如果cnt=9(满10)则txd拉高,如果不满9,就并转串,并且cnt+1
(这个模块我还有点儿没搞懂)
测试:
用户1674220 2011-9-14 17:38