小梅哥和你一起深入学习FPGA之串口调试(一)(下)
那么,特权同学在这里有通过注释解释为什么是12个波特率周期:“我们的标准接收模式下只有1+8+1(2)=11bit的有效数据”。即使是11位,小梅哥还是无法理解为什么需要12个波特率时钟。我们在实际使用的时候,一般不去考虑校验位的问题,因此总共只有10位,也就是说,我写的10位数据位的仿真模型和特权的11位方式不兼容。考虑到大多数的应用过程中是10位,因此小梅哥在特权大神的代码上稍作修改,以适应10位模式。这里,将第52行代码“else if( num==4'd12 ) begin ”改为“else if( num==4'd10 ) begin ”,将第86行代码“else if( num == 4'd12 ) begin”改为“else if( num == 4'd10 ) begin”。通过这样更改,就能够适应1bit的数据接收。同时,小梅哥在实际调试中发现,第45行的“bps_start_r <= 1'bz ;”代码也存在问题,在复位时,给了bps_start_r一个高阻态,这样在实际仿真时,会导致错误,因此小梅哥在这里,将这一行代码进行了修改,复位时将bps_start_r置为0,即修改为“bps_start_r <= 1'b0 ;”。
本文引用地址:https://www.eepw.com.cn/article/283060.htm以上为接收部分的修改。发送部分的波特率波形如下所示:

同样有11个波特率时钟,因此,小梅哥将发送部分的代码稍作修改,以适应10bit的数据发送。特权同学原始代码如下:
41 always @ ( posedge clk or negedge rst_n ) begin
42 if(! rst_n ) begin
43 bps_start_r <= 1'bz ;
44 tx_en <= 1'b0 ;
45 tx_data <= 8'd0 ;
46 end
47 else if( neg_rx_int ) begin //
48 bps_start_r <= 1'b1 ;
49 tx_data <= rx_data ; //
50 tx_en <= 1'b1 ; //
51 end
52 else if( num==4'd11 ) begin //
53 bps_start_r <= 1'b0 ;
54 tx_en <= 1'b0 ;
55 end
56 end
57
58 assign bps_start = bps_start_r ;
59
60//---------------------------------------------------------
61 reg rs232_tx_r ;
62
63 always @ ( posedge clk or negedge rst_n ) begin
64 if(! rst_n ) begin
65 num <= 4'd0 ;
66 rs232_tx_r <= 1'b1 ;
67 end
68 else if( tx_en ) begin
69 if( clk_bps ) begin
70 num <= num+1'b1 ;
71 case ( num)
72 4'd0 : rs232_tx_r <= 1'b0 ; //
73 4'd1 : rs232_tx_r <= tx_data [0]; // bit0
74 4'd2 : rs232_tx_r <= tx_data [1]; // bit1
75 4'd3 : rs232_tx_r <= tx_data [2];// bit2
76 4'd4 : rs232_tx_r <= tx_data [3]; // bit3
77 4'd5 : rs232_tx_r <= tx_data [4];// bit4
78 4'd6 : rs232_tx_r <= tx_data [5]; // bit5
79 4'd7 : rs232_tx_r <= tx_data [6]; // bit6
80 4'd8 : rs232_tx_r <= tx_data [7]; // bit7
81 4'd9 : rs232_tx_r <= 1'b1 ; //
82 default : rs232_tx_r <= 1'b1 ;
83 endcase
84 end
85 else if( num==4'd11 ) num <= 4'd0 ; //
86 end
87 end
88
这里,我们将第52行代码“else if( num==4'd11 ) begin”修改为“else if( num==4'd10 ) begin”,将第85行代码“else if( num==4'd11 ) num <= 4'd0 ;”修改为“else if( num==4'd10 ) num <= 4'd0 ;”同样,第43行,针对“bps_start_r <= 1'bz;”也进行了与接收部分相同的修改,即修改为“bps_start_r <= 1'b0 ;”其他部分不变,然后再进行仿真编译测试。仿真结果如下:

由以上仿真结果可知,通过修改,该串口模块已经能够实现正确的收发了。接下来,小梅哥将通过板级验证来对该模块进行测试。
这里,小梅哥使用至芯科技提供的一块入门级FPGA开发板来完成该模块的板级验证。以下为该开发板的照片:


该开发板上集成了一枚PL2303的USB转串口芯片,因此,我们不再需要笨拙的9针串口线,只需要一根USB线将开发板与电脑的USB口相连,再安装PL2303的驱动,即可在PC端模拟出一个串口端口,该串口端口的使用和传统串口端口没有任何差别。具体的串口驱动安装过程如下图所示:





通过以上步骤,我们就实现了PL2303型USB转串口芯片驱动的安装。接下来,我们需要根据各自使用的开发板的电路分配引脚,这里小梅哥先用图文的形式介绍一下针对ZX2开发板的引脚分配及最终将配置文件下载到开发板的流程:






通过以上步骤,电路就已经成功的配置到了我们的开发板上并运行起来了,这个时候,我们就需要通过调试软件来进行调试,以验证我们修改后的UART收发模块能否稳定运行。要调试我们的设计,我们还需要一个串口调试工具,通过串口调试工具,对我们编写的串口模块持续发送数据,然后接收串口模块发送回来的数据,通过对比发送与接收的数据,如果相同,则表明我们的模块是能够稳定工作的,如果出现丢码或者乱码,表明收发过程中出现了错误,则表明我们设计的模块存在工作不稳定的情况,需要进一步修改优化。
这里,我们使用程序匠人前辈编写的强大串口调试软件——串口猎人。该软件的下载和安装小梅哥就不多说了,当我们启动串口猎人软件后,会显示以下界面,接下来小梅哥就直接以图片配文字的形式来一步一步演示该软件的使用:



通过以上测试,我们知道了,经过小梅哥的修改,该串口模块目前能够以连续无间隔的发码速度进行收发,而且不存在任何误码和丢码。因此,可以说,小梅哥的修改是成功的。
这一篇,主要带领大家一起进行了串口代码的分析、仿真模型的设计(testbench)、Quartus II软件下使用Nativelink调用Modelsim-altera软件进行仿真、仿真结果简单分析、串口代码的修改、串口模块的板级验证。相信通过此文,初学者能够学到部分知识。
这是该系列文档的第一篇,主要对特权大神的UART代码进行了简单的修改,以适应小梅哥自己的用途。下一篇,小梅哥将详细介绍基于此模块的扩展设计,其实扩展也没多少内容,主要就是加上可变波特率功能,顺便介绍一下代码中一些增加设计灵活性的技巧。第三篇,则是小梅哥开始手把手教大家从原理入手,设计我们自己的UART模块,设计中会加入收发FIFO,并使用标准的Avalon ST接口协议,以形成IP核的形式。
评论