小梅哥和你一起深入学习FPGA之串口调试(一)(下)
时间:01-26
来源:互联网
点击:
以上为小梅哥为了对特权同学的串口收发模块进行测试所展开的部分工作,到这里,仿真测试所需要的准备工作我们就做好了,接下来将实际进行仿真,通过仿真来分析该模块的性能。
这里极力推荐大家使用modelsim进行仿真,因为quartusII自带的仿真工具灵活性和功能都赶modelsim相差甚远。Modelsim作为一款强大的仿真软件,在业界被广泛使用。同时,modelsim针对不同的EDA厂家,也推出了OEM版本,modelsim-altera就是为Altera公司开发的OEM版本,此版本针对Altera公司的器件预先做了许多的工作,使我们使用的时候能够更加的快捷方便,这里,小梅哥就使用modelsim-Altera版本来仿真这个设计。
我们可以使用modelsim-Altera,通过完全手动化的方式来建立仿真工程,添加仿真库、编译文件,添加波形,运行仿真,当然也可以使用Nativelink的方式,通过quartus II软件实现一键调用,实现自动化的仿真过程。这里,对于初学者,小梅哥还是推荐采用这种自动化的方式,因为简单,不需要过多的手动操作,且不容易出错。这里,小梅哥也使用这种方式来进行仿真。
要使用这种方式仿真,我们需要在QuartusII软件中进行EDA Tools的设置。在quartus II软件中,依次点击“tools – options ”,在打开的选项卡中选择“EDA tool options”,在modelsim-altera一栏中输入你的modelsim-Altera的安装路径(部分在安装的时候就已经自动设置好了,就不用去管),如下图所示:
这里设置完成后,点击OK即可。
当确认这一步没有问题后,我们就可以开始进行Nativelink的设置了。Nativelive就是一个链接的过程,通过设置Nativelink,让Quartus II软件能够自动的调用modelsim-altera软件,并建立仿真工程,添加仿真库、编译文件,添加波形,运行仿真。接下来我们就来进行Nativelink的设置
第一步:依次点击“assignments– settings”,
在弹出的选项卡中,选中“EDA Tool Settings”(红色标号1处),在子选项中选择“Simulation”(红色标号2处),注意红色标号5处和6处应分别选择为modelsim-altera和Verilog HDL,如果不是,请通过下拉列表选择为上述选项。点击“Compile test bench” (红色标号3处),然后点击最右侧的“Test Benchs” (红色标号4处),就会弹出如下所示的界面:
点击“New” (红色标号1处),接着会弹出“New Test Bench Settings”界面,如下图所示:
首先我们点击红色标号1处的三个小点,在弹出的文件选择界面中,选中我们需要加入的testbench文件,如下所示:
这里我们选择“Uart_tb.v”和“Uart_module.v”,点击“Open”打开。这里,“Uart_tb.v”为仿真顶层文件,“Uart_module.v”为串口仿真模型。
文件选择好之后,回到New Test Bench Settings界面,如下图所示,
在顶端“test bench name”(红色标号2)处输入我们的仿真顶层文件名,即Uart_tb,注意,不要加“.v”后缀。于是,”Top level module in test bench”会自动与“Test bench name”保持一致。
至此,我们的Nativelink设置就完成了,一路选择OK下去,直到回到Quartus II软件的主界面。此时,我们已经完成了仿真需要的所有设置,我们直接点击Quartus II软件上的RTL Simulation图标
即可启动仿真,也可以通过“Tools– Run Simulation Tool – RTL Simulation”启动仿真。
接下来,我们需要做的就是大约20秒左右的等待,这个过程中,Quartus II会自动启动modelsim-altera软件,建立仿真工程,添加仿真库、编译文件,添加波形,运行仿真。最后停留在如下所示的状态:
这里,右侧深色窗口为波形窗口,下方为副本界面,打印了软件运行过程中的信息,包括添加文件、编译文件、添加波形、运行等,同时还打印了testbench中需要打印输出的信息。具体的打印信息如下:
由此打印信息可知,串口仿真模型总共进行了8次数据发送,却只收到了6次数据,因此有两次发送给串口模块的数据丢失或者串口模块发送的数据不正确。同时,第一次发送出去的数据接收回来还是正确的,但是第二次发送的数据再接收回来,就错误了。这两次数据发送之间的时间间隔为40ns。考虑可能是发送间隔太短导致,但是当第4次发送的数据(s4)被正确接收后(r3),紧接着第5次发送的数据在发回的时候,再次出错,而s4和s5之间间隔了300ns,因此可知,该串口收发模块在连续两次发送间隔很短的情况下,很容易出错。那么,怎么样才能保证连续两次发送之间,即使很短的间隔,也不出错误呢?小梅哥通过对仿真波形的分析发现:一次接收数据,总共有12个波特率脉冲,如下图所示:
这里小梅哥就有点疑惑了,我们一般的应用中,串口一帧的数据为十位,包含1位起始位、8位数据位、一位停止位,一般不含校验位。因此,这里明显多了两个波特率周期,那么,问题很有可能就出在这里。回到这部分的代码:
43 always @ ( posedge clk or negedge rst_n )
44 if(! rst_n ) begin
45 bps_start_r
46 rx_int
47 end
48 else if( neg_rs232_rx ) begin
// rs232_rx
49 bps_start_r
50 rx_int
51 end
52 else if( num==4'd12 ) begin //
53 bps_start_r
54 rx_int
55 end
56
57 assign bps_start = bps_start_r ;
58
59//---------------------------------------------------------
60 reg[ 7 : 0] rx_data_r ; //
61 //---------------------------------------------------------
62
63 reg[ 7 : 0] rx_temp_data ; //
64
65 always @ ( posedge clk or negedge rst_n )
66 if(! rst_n ) begin
67 rx_temp_data
68 num
69 rx_data_r
70 end
71 else if( rx_int ) begin //
72 if( clk_bps ) begin
// , 8bit 1 2
73 num
74 case ( num)
75 4'd1:rx_temp_data[0]
76 4'd2:rx_temp_data [1]
77 4'd3:rx_temp_data [2]
78 4'd4:rx_temp_data [3]
79 4'd5:rx_temp_data [4]
80 4'd6:rx_temp_data [5]
81 4'd7:rx_temp_data [6]
82 4'd8:rx_temp_data [7]
83 default : ;
84 endcase
85 end
86 else if( num == 4'd12 ) begin//我们的标准接收模式下只有1+8+1(2)=11bit的有效数据
87 num
88 rx_data_r
89 end
90 end
那么,特权同学在这里有通过注释解释为什么是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
同样有11个波特率时钟,因此,小梅哥将发送部分的代码稍作修改,以适应10bit的数据发送。特权同学原始代码如下:
41 always @ ( posedge clk or negedge rst_n ) begin
42 if(! rst_n ) begin
43 bps_start_r
44 tx_en
45 tx_data
46 end
47 else if( neg_rx_int ) begin //
48 bps_start_r
49 tx_data
50 tx_en
51 end
52 else if( num==4'd11 ) begin //
53 bps_start_r
54 tx_en
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
66 rs232_tx_r
67 end
68 else if( tx_en ) begin
69 if( clk_bps ) begin
70 num
71 case ( num)
72 4'd0 : rs232_tx_r
73 4'd1 : rs232_tx_r
74 4'd2 : rs232_tx_r
75 4'd3 : rs232_tx_r
76 4'd4 : rs232_tx_r
77 4'd5 : rs232_tx_r
78 4'd6 : rs232_tx_r
79 4'd7 : rs232_tx_r
80 4'd8 : rs232_tx_r
81 4'd9 : rs232_tx_r
82 default : rs232_tx_r
83 endcase
84 end
85 else if( num==4'd11 ) num
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
由以上仿真结果可知,通过修改,该串口模块已经能够实现正确的收发了。接下来,小梅哥将通过板级验证来对该模块进行测试。
这里,小梅哥使用至芯科技提供的一块入门级FPGA开发板来完成该模块的板级验证。以下为该开发板的照片:
该开发板上集成了一枚PL2303的USB转串口芯片,因此,我们不再需要笨拙的9针串口线,只需要一根USB线将开发板与电脑的USB口相连,再安装PL2303的驱动,即可在PC端模拟出一个串口端口,该串口端口的使用和传统串口端口没有任何差别。具体的串口驱动安装过程如下图所示:
通过以上步骤,我们就实现了PL2303型USB转串口芯片驱动的安装。接下来,我们需要根据各自使用的开发板的电路分配引脚,这里小梅哥先用图文的形式介绍一下针对ZX2开发板的引脚分配及最终将配置文件下载到开发板的流程:
通过以上步骤,电路就已经成功的配置到了我们的开发板上并运行起来了,这个时候,我们就需要通过调试软件来进行调试,以验证我们修改后的UART收发模块能否稳定运行。要调试我们的设计,我们还需要一个串口调试工具,通过串口调试工具,对我们编写的串口模块持续发送数据,然后接收串口模块发送回来的数据,通过对比发送与接收的数据,如果相同,则表明我们的模块是能够稳定工作的,如果出现丢码或者乱码,表明收发过程中出现了错误,则表明我们设计的模块存在工作不稳定的情况,需要进一步修改优化。
这里,我们使用程序匠人前辈编写的强大串口调试软件——串口猎人。该软件的下载和安装小梅哥就不多说了,当我们启动串口猎人软件后,会显示以下界面,接下来小梅哥就直接以图片配文字的形式来一步一步演示该软件的使用:
通过以上测试,我们知道了,经过小梅哥的修改,该串口模块目前能够以连续无间隔的发码速度进行收发,而且不存在任何误码和丢码。因此,可以说,小梅哥的修改是成功的。
这一篇,主要带领大家一起进行了串口代码的分析、仿真模型的设计(testbench)、Quartus II软件下使用Nativelink调用Modelsim-altera软件进行仿真、仿真结果简单分析、串口代码的修改、串口模块的板级验证。相信通过此文,初学者能够学到部分知识。
这是该系列文档的第一篇,主要对特权大神的UART代码进行了简单的修改,以适应小梅哥自己的用途。下一篇,小梅哥将详细介绍基于此模块的扩展设计,其实扩展也没多少内容,主要就是加上可变波特率功能,顺便介绍一下代码中一些增加设计灵活性的技巧。第三篇,则是小梅哥开始手把手教大家从原理入手,设计我们自己的UART模块,设计中会加入收发FIFO,并使用标准的Avalon ST接口协议,以形成IP核的形式。
这里极力推荐大家使用modelsim进行仿真,因为quartusII自带的仿真工具灵活性和功能都赶modelsim相差甚远。Modelsim作为一款强大的仿真软件,在业界被广泛使用。同时,modelsim针对不同的EDA厂家,也推出了OEM版本,modelsim-altera就是为Altera公司开发的OEM版本,此版本针对Altera公司的器件预先做了许多的工作,使我们使用的时候能够更加的快捷方便,这里,小梅哥就使用modelsim-Altera版本来仿真这个设计。
我们可以使用modelsim-Altera,通过完全手动化的方式来建立仿真工程,添加仿真库、编译文件,添加波形,运行仿真,当然也可以使用Nativelink的方式,通过quartus II软件实现一键调用,实现自动化的仿真过程。这里,对于初学者,小梅哥还是推荐采用这种自动化的方式,因为简单,不需要过多的手动操作,且不容易出错。这里,小梅哥也使用这种方式来进行仿真。
要使用这种方式仿真,我们需要在QuartusII软件中进行EDA Tools的设置。在quartus II软件中,依次点击“tools – options ”,在打开的选项卡中选择“EDA tool options”,在modelsim-altera一栏中输入你的modelsim-Altera的安装路径(部分在安装的时候就已经自动设置好了,就不用去管),如下图所示:
这里设置完成后,点击OK即可。
当确认这一步没有问题后,我们就可以开始进行Nativelink的设置了。Nativelive就是一个链接的过程,通过设置Nativelink,让Quartus II软件能够自动的调用modelsim-altera软件,并建立仿真工程,添加仿真库、编译文件,添加波形,运行仿真。接下来我们就来进行Nativelink的设置
第一步:依次点击“assignments– settings”,
在弹出的选项卡中,选中“EDA Tool Settings”(红色标号1处),在子选项中选择“Simulation”(红色标号2处),注意红色标号5处和6处应分别选择为modelsim-altera和Verilog HDL,如果不是,请通过下拉列表选择为上述选项。点击“Compile test bench” (红色标号3处),然后点击最右侧的“Test Benchs” (红色标号4处),就会弹出如下所示的界面:
点击“New” (红色标号1处),接着会弹出“New Test Bench Settings”界面,如下图所示:
首先我们点击红色标号1处的三个小点,在弹出的文件选择界面中,选中我们需要加入的testbench文件,如下所示:
这里我们选择“Uart_tb.v”和“Uart_module.v”,点击“Open”打开。这里,“Uart_tb.v”为仿真顶层文件,“Uart_module.v”为串口仿真模型。
文件选择好之后,回到New Test Bench Settings界面,如下图所示,
在顶端“test bench name”(红色标号2)处输入我们的仿真顶层文件名,即Uart_tb,注意,不要加“.v”后缀。于是,”Top level module in test bench”会自动与“Test bench name”保持一致。
至此,我们的Nativelink设置就完成了,一路选择OK下去,直到回到Quartus II软件的主界面。此时,我们已经完成了仿真需要的所有设置,我们直接点击Quartus II软件上的RTL Simulation图标
即可启动仿真,也可以通过“Tools– Run Simulation Tool – RTL Simulation”启动仿真。
接下来,我们需要做的就是大约20秒左右的等待,这个过程中,Quartus II会自动启动modelsim-altera软件,建立仿真工程,添加仿真库、编译文件,添加波形,运行仿真。最后停留在如下所示的状态:
这里,右侧深色窗口为波形窗口,下方为副本界面,打印了软件运行过程中的信息,包括添加文件、编译文件、添加波形、运行等,同时还打印了testbench中需要打印输出的信息。具体的打印信息如下:
由此打印信息可知,串口仿真模型总共进行了8次数据发送,却只收到了6次数据,因此有两次发送给串口模块的数据丢失或者串口模块发送的数据不正确。同时,第一次发送出去的数据接收回来还是正确的,但是第二次发送的数据再接收回来,就错误了。这两次数据发送之间的时间间隔为40ns。考虑可能是发送间隔太短导致,但是当第4次发送的数据(s4)被正确接收后(r3),紧接着第5次发送的数据在发回的时候,再次出错,而s4和s5之间间隔了300ns,因此可知,该串口收发模块在连续两次发送间隔很短的情况下,很容易出错。那么,怎么样才能保证连续两次发送之间,即使很短的间隔,也不出错误呢?小梅哥通过对仿真波形的分析发现:一次接收数据,总共有12个波特率脉冲,如下图所示:
这里小梅哥就有点疑惑了,我们一般的应用中,串口一帧的数据为十位,包含1位起始位、8位数据位、一位停止位,一般不含校验位。因此,这里明显多了两个波特率周期,那么,问题很有可能就出在这里。回到这部分的代码:
43 always @ ( posedge clk or negedge rst_n )
44 if(! rst_n ) begin
45 bps_start_r
46 rx_int
47 end
48 else if( neg_rs232_rx ) begin
// rs232_rx
49 bps_start_r
50 rx_int
51 end
52 else if( num==4'd12 ) begin //
53 bps_start_r
54 rx_int
55 end
56
57 assign bps_start = bps_start_r ;
58
59//---------------------------------------------------------
60 reg[ 7 : 0] rx_data_r ; //
61 //---------------------------------------------------------
62
63 reg[ 7 : 0] rx_temp_data ; //
64
65 always @ ( posedge clk or negedge rst_n )
66 if(! rst_n ) begin
67 rx_temp_data
68 num
69 rx_data_r
70 end
71 else if( rx_int ) begin //
72 if( clk_bps ) begin
// , 8bit 1 2
73 num
74 case ( num)
75 4'd1:rx_temp_data[0]
76 4'd2:rx_temp_data [1]
77 4'd3:rx_temp_data [2]
78 4'd4:rx_temp_data [3]
79 4'd5:rx_temp_data [4]
80 4'd6:rx_temp_data [5]
81 4'd7:rx_temp_data [6]
82 4'd8:rx_temp_data [7]
83 default : ;
84 endcase
85 end
86 else if( num == 4'd12 ) begin//我们的标准接收模式下只有1+8+1(2)=11bit的有效数据
87 num
88 rx_data_r
89 end
90 end
那么,特权同学在这里有通过注释解释为什么是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
同样有11个波特率时钟,因此,小梅哥将发送部分的代码稍作修改,以适应10bit的数据发送。特权同学原始代码如下:
41 always @ ( posedge clk or negedge rst_n ) begin
42 if(! rst_n ) begin
43 bps_start_r
44 tx_en
45 tx_data
46 end
47 else if( neg_rx_int ) begin //
48 bps_start_r
49 tx_data
50 tx_en
51 end
52 else if( num==4'd11 ) begin //
53 bps_start_r
54 tx_en
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
66 rs232_tx_r
67 end
68 else if( tx_en ) begin
69 if( clk_bps ) begin
70 num
71 case ( num)
72 4'd0 : rs232_tx_r
73 4'd1 : rs232_tx_r
74 4'd2 : rs232_tx_r
75 4'd3 : rs232_tx_r
76 4'd4 : rs232_tx_r
77 4'd5 : rs232_tx_r
78 4'd6 : rs232_tx_r
79 4'd7 : rs232_tx_r
80 4'd8 : rs232_tx_r
81 4'd9 : rs232_tx_r
82 default : rs232_tx_r
83 endcase
84 end
85 else if( num==4'd11 ) num
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
由以上仿真结果可知,通过修改,该串口模块已经能够实现正确的收发了。接下来,小梅哥将通过板级验证来对该模块进行测试。
这里,小梅哥使用至芯科技提供的一块入门级FPGA开发板来完成该模块的板级验证。以下为该开发板的照片:
该开发板上集成了一枚PL2303的USB转串口芯片,因此,我们不再需要笨拙的9针串口线,只需要一根USB线将开发板与电脑的USB口相连,再安装PL2303的驱动,即可在PC端模拟出一个串口端口,该串口端口的使用和传统串口端口没有任何差别。具体的串口驱动安装过程如下图所示:
通过以上步骤,我们就实现了PL2303型USB转串口芯片驱动的安装。接下来,我们需要根据各自使用的开发板的电路分配引脚,这里小梅哥先用图文的形式介绍一下针对ZX2开发板的引脚分配及最终将配置文件下载到开发板的流程:
通过以上步骤,电路就已经成功的配置到了我们的开发板上并运行起来了,这个时候,我们就需要通过调试软件来进行调试,以验证我们修改后的UART收发模块能否稳定运行。要调试我们的设计,我们还需要一个串口调试工具,通过串口调试工具,对我们编写的串口模块持续发送数据,然后接收串口模块发送回来的数据,通过对比发送与接收的数据,如果相同,则表明我们的模块是能够稳定工作的,如果出现丢码或者乱码,表明收发过程中出现了错误,则表明我们设计的模块存在工作不稳定的情况,需要进一步修改优化。
这里,我们使用程序匠人前辈编写的强大串口调试软件——串口猎人。该软件的下载和安装小梅哥就不多说了,当我们启动串口猎人软件后,会显示以下界面,接下来小梅哥就直接以图片配文字的形式来一步一步演示该软件的使用:
通过以上测试,我们知道了,经过小梅哥的修改,该串口模块目前能够以连续无间隔的发码速度进行收发,而且不存在任何误码和丢码。因此,可以说,小梅哥的修改是成功的。
这一篇,主要带领大家一起进行了串口代码的分析、仿真模型的设计(testbench)、Quartus II软件下使用Nativelink调用Modelsim-altera软件进行仿真、仿真结果简单分析、串口代码的修改、串口模块的板级验证。相信通过此文,初学者能够学到部分知识。
这是该系列文档的第一篇,主要对特权大神的UART代码进行了简单的修改,以适应小梅哥自己的用途。下一篇,小梅哥将详细介绍基于此模块的扩展设计,其实扩展也没多少内容,主要就是加上可变波特率功能,顺便介绍一下代码中一些增加设计灵活性的技巧。第三篇,则是小梅哥开始手把手教大家从原理入手,设计我们自己的UART模块,设计中会加入收发FIFO,并使用标准的Avalon ST接口协议,以形成IP核的形式。
仿真 EDA Altera 自动化 Quartus Verilog FPGA USB 电路 相关文章:
- 基于FPGA的片上系统的无线保密通信终端(02-16)
- 基于ARM的嵌入式系统中从串配置FPGA的实现(06-09)
- 采用EEPROM对大容量FPGA芯片数据实现串行加载(03-18)
- 基于PLB总线的H.264整数变换量化软核的设计(03-20)
- FPGA按键模式的研究与设计(03-24)
- 验证FPGA设计:模拟,仿真,还是碰运气?(08-04)