用户工具

站点工具


icore4tfpga_19

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
icore4tfpga_19 [2020/03/10 11:28]
zgf [五、 实验步骤及实验结果]
icore4tfpga_19 [2022/04/01 11:04] (当前版本)
sean
行 2: 行 2:
 |技术支持电话|**0379-69926675-801**||| |技术支持电话|**0379-69926675-801**|||
 |技术支持邮件|Gingko@vip.163.com||| |技术支持邮件|Gingko@vip.163.com|||
-|技术论坛|http://​www.eeschool.org||| 
 ^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^ ^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^
-|  V1.0  |  2020-03-10  ​| ​ gingko ​ |  初次建立 ​ | +|  V1.0  |  2020-03-05  ​| ​ gingko ​ |  初次建立 ​ | 
  
 +===== 实验十九:Modelsim 仿真实验 =====
  
-===== 实验十九:串口通信实验——基于FPGA实现UART信 =====+==== 一、 了解 Modelsim ​==== 
 +  
 +  * Modelsim 仿真工具是 Mentor 公司开发的业界优秀的HDL语言仿真软件,支持 Verilog、VHDL 以及他们的混合仿真,方便的图形化界面,强大的仿真能力。是 ​FPGA设计中最用的一种仿真工具之一。 ​  
 +===二、Modelsim 安装 ​==== 
 +  
 +1、双击 modelsim-win32-10.1a-se.exe 文件开始安装。 
 +{{ :​icore4t:​icore4t_fpga_29_1.jpg?​direct |}} 
 +2、双击.exe 文件后进入如下界面,点击 Next。  
 +{{ :​icore4t:​icore4t_fpga_29_2.jpg?​direct |}} 
 +3、在框 1 处选择安装路径,然后点击 Next。  
 +{{ :​icore4t:​icore4t_fpga_29_3.jpg?​direct |}} 
 +4、此界面点击 Agree 即可进入下一步的安装。  
 +{{ :​icore4t:​icore4t_fpga_29_4.jpg?​direct |}} 
 +5、接下来进入进度条界面,此过程中弹出的界面全部点击 Yes。 
 +{{ :​icore4t:​icore4t_fpga_29_5.jpg?​direct |}} 
 +6、此界面点击 Yes 进入下一个安装步骤。  
 +{{ :​icore4t:​icore4t_fpga_29_6.jpg?​direct |}} 
 +7、点击 Yes,电脑立即重启;点击 No,可在空闲时手动重启。此时安装结束。 
 +{{ :​icore4t:​icore4t_fpga_29_7.jpg?​direct |}}
  
-==== 、 实验目的与意义 ​==== +**备注:关于破解请参考网络资料或者iCore4TX下的Modelsim实验例程文档。** 
-  - 掌握UART协议及实现方法。 +==== Modelsim 仿真工具调用 ​==== 
-  - 掌握QuartusII使用。 +  
-==== 、 实验设备及平台 ​====+1、打开软件,编写 modelsim 工程(也可直接打开自带例程),然后编译保存,如图所示:  
 +{{ :​icore4t:​icore4t_fpga_29_8.jpg?​direct |}} 
 +  
 +2、打开 Assignments->​Settings->​Simulation,然后根据图示设置,设置完毕点击 OK。  
 +{{ :​icore4t:​icore4t_fpga_29_9.jpg?​direct |}}   
 +3、打开 Processing ​->​Star->​Star Test Template Writer。  
 +{{ :​icore4t:​icore4t_fpga_29_10.jpg?​direct |}}   
 +3、打开 File->​Open->​simulation->​modelsim,找到 modelsim.vt 所在路径,然后选中打开。  
 +{{ :​icore4t:​icore4t_fpga_29_11.jpg?​direct |}}   
 +4、打开文本后根据下图所示对工程文件进行修改,然后点击保存。  
 +{{ :​icore4t:​icore4t_fpga_29_12.jpg?​direct |}}   
 +5、打开 Tools -> Options,进入 Options 界面后点击框 1 处,并在框 2 处选择 Modelsim.exe ​路径,然后点击 OK。  
 +{{ :​icore4t:​icore4t_fpga_29_13.jpg?​direct |}}   
 +6、打开 Assignments->​Settings->​Simulation,查看步骤 2 的设置是否有变化,如有不同请重复设置一下,然后点击框 1 处 Test Benches 进行设置。  
 +{{ :​icore4t:​icore4t_fpga_29_14.jpg?​direct |}}   
 +8、点击 New,根据图示对框 1 和框 2 处进行设置,点击框 3 处选择 modelsim.vt 文件,选择后并点击框 3 后面的 Add,最后点击 OK 结束。  
 +{{ :​icore4t:​icore4t_fpga_29_15.jpg?​direct |}}   
 +{{ :​icore4t:​icore4t_fpga_29_16.jpg?​direct |}}  
 +{{ :​icore4t:​icore4t_fpga_29_17.jpg?​direct |}}  
 +9、所有设置完毕后点击保存并编译,然后点击框 1 按钮进行仿真。  
 +{{ :​icore4t:​icore4t_fpga_29_18.jpg?​direct |}} 
 +10、 仿真波形界面如下图所示。 
 +{{ :​icore4t:​icore4t_fpga_29_19.jpg?​direct |}} 
 +==== 、实验现象 ​==== 
 +  
 +  * 通过仿真波形,可以清晰的看到所添加信号波形的变化与程序所写的一致。
  
-  - iCore4T 双核心板。[[https://​item.taobao.com/​item.htm?​spm=a1z10.1-c.w137644-251734891.3.5923532fDrMDOe&​id=610595120319|点击购买]] 
-  - iCore4T底板(杜邦线一套)。 
-  - iTool3(带串口TTL和Blaster功能)。[[https://​item.taobao.com/​item.htm?​id=554869837940|点击购买]] 
-  - Micro USB线缆。 
-  - Keil MDK 开发平台。 
-  - Quartus开发平台。 
-  - 电脑一台。 
-==== 三、 实验原理 ==== 
  
-  * UART(通用异步收发器)是一种通用串行数据总线,用于异步通信,可实现全双工传输和接收,是做硬件开发时常用的一种硬件接口。USART(通用同步异步收发器)在UART的基础上增加了同步功能,即USART是UART的增强型,异步通信的时候和UART没有区别。 ​    ​UART通信具有两根信号线,一根用于发送数据,一根用于接收数据。然而数据的传输是按照字节进行传输的,因此在发送时需要将并行数据转换成串行数据,接收时需要将串行数据转换成并行数据。 
-  * UART通信传输是以帧位单位的,每帧数据有4部分构成:起始位、数据位、奇偶校验位和停止位。以8位字长的串口发送数据帧为例,其帧协议如图19.1所示,从图中可以看到,初始状态时,传输线上为高电平,在持续一个波特的低电平之后,是发送的有效数据。之后是至少一个波特高电平的停止位。 
-{{ :​icore4t:​icore4t_fpga_19_1.png?​direct |图19.1}} 
  
-  * 在UART通信中有一个重要的参数,即波特率,它表征了串口的传输速度,表示1秒内传输的二进制位的个数,波特率越大速度越快,反之,越慢。 
-  * UART接线原则:RX<​--- --->​TX,​TX<​--- --->​RX,如图19.2所示。 
-{{ :​icore4t:​icore4t_fpga_19_2.png?​direct&​500 |图19.2}} 
- 
-==== 四、 代码讲解 ==== 
- 
-  * 本实验以115200波特率为例,表示1秒钟传输115200个二进制位,每位传输需要时间位1/​115200s,为保证每位数据被锁存时处于稳定状态,所以尽量保证在每位的中间位置进行锁存。本实验采用的是16等分的方法,即利用高频时钟(16倍波特率,该时钟由锁相环提供)将每位数据进行16等分,同时进行计数,当计数到8时可保证时钟处于数据的中间位置,此时对数据进行锁存。本实验的整个流程:首先,通过串口调试助手发送一字节的任意数据;FPGA收到该数据后,直接将数据返还给调试助手。 
-  * 在整个实现过程中最主要的模块有发送模块和接收模块两个。其中接收模块主要负责接收信号线上的串行数据,将数据转换成并行数据,接收完成并产生一个接收完成标志。整个过程由状态机实现,其代码如下: 
-<code verilog> 
-/​*************************************************/​ 
-//​接收模块 
-always @ (posedge pll_1_8m or negedge rst_n) 
-    begin 
-        if(!rst_n) 
-            begin 
-                rx_cnt <= 8'd0;; 
-                uart_rdata_r <= 8'd0; 
-                uart_rdata <= 8'd0; 
-                parity_bit <= 1'd0; 
-                receive_over_r <= 1'd0; 
-            end 
-        else  
-            begin 
-                case(rx_cnt) 
-                    //​判断信号线是否有变化(信号线正常情况下位高电平,有低电平表示信号有变化) 
-                    8'​d0:​begin 
-                        if(!rxd) 
-                            begin 
-                                rx_cnt <= rx_cnt + 1'd1; 
-                            end 
-                        else 
-                            begin 
-                                rx_cnt <= rx_cnt; 
-                            end              
-                    end 
-                    //​判断信号线变化是否为数据起始位(信号线稳定后仍为低电平,表示为真正的数据起始位) 
-                    8'​d8:​begin 
-                        if(!rxd) 
-                            begin 
-                                rx_cnt <= rx_cnt + 1'd1; 
-                            end 
-                        else 
-                            begin 
-                                rx_cnt <= 8'd0; 
-                            end 
-                    end 
-                    //​接收数据0位 
-                    8'​d24:​begin 
-                        uart_rdata_r[0] <= rxd; 
-                        rx_cnt <= rx_cnt + 1'd1; 
-                    end 
-                    //​接收数据1位 
-                    8'​d40:​begin 
-                        uart_rdata_r[1] <= rxd; 
-                        rx_cnt <= rx_cnt + 1'd1; 
-                    end 
-                    //​接收数据2位 
-                    8'​d56:​begin 
-                        uart_rdata_r[2] <= rxd; 
-                        rx_cnt <= rx_cnt + 1'd1; 
-                    end 
-                    //​接收数据3位 
-                    8'​d72:​begin 
-                        uart_rdata_r[3] <= rxd; 
-                        rx_cnt <= rx_cnt + 1'd1; 
-                    end 
-                    //​接收数据4位 
-                    8'​d88:​begin 
-                        uart_rdata_r[4] <= rxd; 
-                        rx_cnt <= rx_cnt + 1'd1; 
-                    end 
-                    //​接收数据5位 
-                    8'​d104:​begin 
-                        uart_rdata_r[5] <= rxd; 
-                        rx_cnt <= rx_cnt + 1'd1; 
-                    end 
-                    //​接收数据6位 
-                    8'​d120:​begin 
-                        uart_rdata_r[6] <= rxd; 
-                        rx_cnt <= rx_cnt + 1'd1; 
-                    end 
-                    //​接收数据7位 
-                    8'​d136:​begin 
-                        uart_rdata_r[7] <= rxd; 
-                        rx_cnt <= rx_cnt + 1'd1; 
-                    end 
-                    //​接收校验位(无校验) 
-                    8'​d152:​begin 
-                        parity_bit <= rxd; 
-                        rx_cnt <= rx_cnt + 1'd1; 
-                    end 
-                    //​接收停止位 
-                    8'​d168:​begin 
-                        rx_cnt <= rx_cnt + 1'd1; 
-                        uart_rdata <= uart_rdata_r;​ 
-                    end 
-                    ​ 
-                    //​接收完成标志拉高两个时钟 
-                    8'​d175:​begin 
-                        receive_over_r <= 1'd1; 
-                        rx_cnt <= rx_cnt + 1'd1; 
-                    end 
-                    8'​d177:​begin 
-                        receive_over_r <= 1'd0; 
-                        rx_cnt <= rx_cnt + 1'd1; 
-                    end 
-                    //​判断是否发送完成 
-                    8'​d178:​begin 
-                        if(send_over) 
-                            begin 
-                                rx_cnt <= 8'd0; 
-                            end 
-                        else 
-                            begin 
-                                rx_cnt <= rx_cnt; 
-                            end 
-                    end 
-                    default:​begin 
-                        rx_cnt <= rx_cnt + 1'​d1; ​                   ​ 
-                    end 
-                endcase 
-            end 
-    end 
-/​*************************************************/​ 
-</​code>​ 
-发送模块主要负责将接收到的完整数据转换成串行数据,通过发送信号线串行输出,发送完成后产生发送完成标志。其代码如下: 
-<code verilog> 
-/​*************************************************/​ 
-//​发送模块 
-always @ (posedge pll_1_8m or negedge rst_n) 
-begin 
-    if(!rst_n) 
-        begin 
-            tx_cnt <= 8'​d255;​ 
-            tx_r <= 1'd1; 
-            send_over_r <= 1'd0; 
-        end 
-    else  
-        begin 
-            case(tx_cnt) 
-                8'​d255:​begin 
-                    if(receive_over) 
-                        begin 
-                            tx_cnt <= tx_cnt + 1'd1; 
-                        end 
-                    else 
-                        begin 
-                            tx_cnt <= tx_cnt; 
-                        end 
-                end 
-                8'​d0:​begin 
-                    tx_cnt <= tx_cnt + 1'd1; 
-                    tx_r <= 1'​d0;//​发送起始位 
-                end 
-                8'​d16:​begin ​                                                         
-                    tx_cnt <= tx_cnt + 1'd1; 
-                    tx_r <= tx_data[0];//​发送数据0位 
-                end 
-                8'​d32:​begin 
-                    tx_cnt <= tx_cnt + 1'd1; 
-                    tx_r <= tx_data[1];//​发送数据1位 
-                end 
-                8'​d48:​begin 
-                    tx_cnt <= tx_cnt + 1'd1; 
-                    tx_r <= tx_data[2];//​发送数据2位 
-                end 
-                8'​d64:​begin 
-                    tx_cnt <= tx_cnt + 1'd1; 
-                    tx_r <= tx_data[3];//​发送数据3位 
-                end  
-                8'​d80:​begin 
-                    tx_cnt <= tx_cnt + 1'd1; 
-                    tx_r <= tx_data[4];//​发送数据4位 
-                end 
-                8'​d96:​begin 
-                    tx_cnt <= tx_cnt + 1'd1; 
-                    tx_r <= tx_data[5];//​发送数据5位 
-                end 
-                8'​d112:​begin 
-                    tx_cnt <= tx_cnt + 1'd1; 
-                    tx_r <= tx_data[6];//​发送数据6位 
-                end 
-                8'​d128:​begin 
-                    tx_cnt <= tx_cnt + 1'd1; 
-                    tx_r <= tx_data[7];//​发送数据7位 
-                end 
-                8'​d144:​begin 
-                    tx_cnt <= tx_cnt + 1'd1; 
-                    tx_r <= 1'​bz; ​      //​发送校验位 ​               
-                end 
-                8'​d160:​begin 
-                    tx_cnt <= tx_cnt + 1'd1; 
-                    tx_r <= 1'​d1;//​发送停止位 
-                end  
-                8'​d168:​begin 
-                    tx_cnt <= tx_cnt + 8'd1; 
-                    tx_r <= 1'​d1; ​          //​一帧数据发送结束 ​   
-                end 
-                8'​d175:​begin 
-                    tx_cnt <= tx_cnt + 8'd1; 
-                    send_over_r <= 1'd1; 
-                end 
-                8'​d177:​begin 
-                    tx_cnt <= 8'​d255;​ 
-                    send_over_r <= 1'd0; 
-                end 
-                default:​begin 
-                    tx_cnt <= tx_cnt + 8'd1; 
-                    tx_r <= tx_r; 
-                end 
-            endcase 
-        end 
-end 
-/​*************************************************/​ 
-</​code>​ 
-==== 五、 实验步骤及实验结果 ==== 
- 
-  * 1、将硬件正确连接,如图19.3所示。 
-{{ :​icore4t:​icore4t_fpga_19_3.jpg?​direct |图19.3}} 
- 
-  * 2、将编写好的代码进行编译,并下载到开发板中; 
-  * 3、打开串口调试工具,波特率设置为115200,并打开对应端口,如图19.4所示; 
-{{ :​icore4t:​icore4t_fpga_19_4.png?​direct |图19.4}} 
- 
-  * 4、在输入去发送一个字节的数据,FPGA会自动返回该数据,如图19.5所示。 
-{{ :​icore4t:​icore4t_fpga_19_5.png?​direct |图19.5}} 
- 
-==== 六、 拓展实验 ==== 
- 
-1、通过Signaltap观察串口通信时序。 
  
icore4tfpga_19.1583810900.txt.gz · 最后更改: 2020/03/10 11:28 由 zgf