用户工具

站点工具


icore4tfpga_16

差别

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

到此差别页面的链接

后一修订版
前一修订版
icore4tfpga_16 [2020/02/26 10:05]
zgf 创建
icore4tfpga_16 [2024/04/10 15:26] (当前版本)
zhaowenzhe [五、 实验步骤及实验结果]
行 2: 行 2:
 |技术支持电话|**0379-69926675-801**||| |技术支持电话|**0379-69926675-801**|||
 |技术支持邮件|Gingko@vip.163.com||| |技术支持邮件|Gingko@vip.163.com|||
-|技术论坛|http://​www.eeschool.org||| 
 ^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^ ^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^
-|  V1.0  |  ​2019-02-26 ​ |  gingko ​ |  初次建立 ​ | +|  V1.0  |  ​2020-02-26 ​ |  gingko ​ |  初次建立 ​ | 
  
-===== 实验十六:PWM输出实验——不同PWM输出 ​=====+===== 实验十六:串口通信实验——基于FPGA实现UART通信 ​=====
  
 ==== 一、 实验目的与意义 ==== ==== 一、 实验目的与意义 ====
-  - 掌握输出不同PWM的原理及方法。 + 
-  - 掌握宏定义、参数变量的使用方法。+  - 掌握UART协议及实现方法。
   - 掌握QuartusII的使用方法。   - 掌握QuartusII的使用方法。
 ==== 二、 实验设备及平台 ==== ==== 二、 实验设备及平台 ====
-  ​- iCore4T 双核心板。[[https://​item.taobao.com/​item.htm?​spm=a1z10.1-c.w137644-251734891.3.5923532fDrMDOe&​id=610595120319|点击购买]] + 
-  - Blaster(或相同功能)仿真器。[[https://​item.taobao.com/​item.htm?​id=554869837940|点击购买]]+  ​- iCore4T 双核心板。 
 +  ​iCore4T 底板(杜邦线一套)。 
 +  ​iTool3(串口TTL)。 
 +  - Blaster(或相同功能)仿真器。
   - Micro USB线缆。   - Micro USB线缆。
   - Keil MDK 开发平台。   - Keil MDK 开发平台。
行 20: 行 22:
   - 电脑一台。   - 电脑一台。
 ==== 三、 实验原理 ==== ==== 三、 实验原理 ====
-  * PWM全称是Pulse Width Modulation,是脉冲宽度调制缩写。。它是通过对脉冲宽度进调制等效出所需要的波形。在PWM波形属性中频率占空比两个非重要参数而本实验的主要目的就是过FPGA硬件语言描述实现不频率、占空比PWM信号输出 +  * UART(通用异步收发器)一种用串数据总线用于异步通信,可实现全双工传输和接收,做硬件开发时一种硬件接口USART(用同步异步收发器)在UART基础上增加了步功能,即USART是UART增强型,异步通信的时候和UART没有区别。 ​    ​UART通信具有两根信号线,一根用于发送数据,一根用于接收数据然而数据传输按照字节进行传输的,因此在发送需要将并行数据转换成串行数据接收时需要将串行数据转换成并行数据。 
-  * FPGA产生不同频率不同占空比的原理基于计数器实现的,通过对参考钟进数,控制某个号高低电平出实现频率和占空比变化。其实现原理如图11.1所示,通过改变puty值改变pwm的占空比通过改变cycle值改变pwm频率。 +  * UART通是以帧位单位,每帧数据有4部分构成:起始位、数据位、奇偶校验位和停止位以8位字长的串口发送数据帧为例,帧协议如图16.1所示,从图中可以看到,初始状态时,传输线上为高电平,在持续一个波特低电平之后是发送有效数据。之后是至少一个波特高电平停止位。 
-{{ :​icore4t:​icore4t_fpga_16_1.png?​direct |图16.1}} +{{ :​icore4t:​icore4t_fpga_16_1.png?​direct&​800 ​|}} 
 +  * 在UART通信中有一个重要的参数,即波特率,它表征了串口的传输速度,表示1秒内传输的二进制位的个数,波特率越大速度越快,反之,越慢。 
 +  * UART接线原则:RX←→TX,​TX←→RX,如图16.2所示。 
 +{{ :​icore4t:​icore4t_fpga_16_2.png?​direct&​300 |}}
 ==== 四、 代码讲解 ==== ==== 四、 代码讲解 ====
-  ​* 本实验原理通过参考时钟进行计数,并在时钟器特定进行高低电平的变换,来改变输出波形的频率和占空比。本实验中参考时钟为clk_25m频率控制参为cycle占空比参为puty_50puty_20频率为500KHz波形计算方公式为clk_25m/(cycle-1);占空比20%的参计算公式:puty_20/​cycle;​ 占空比50%计算公式为:puty_50/cycle。其代码如下:+ 
 +  ​* 本实验以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> <code verilog>
-     always@(posedge ​clk_25m ​or negedge rst_n)+/​*************************************************/​ 
 +//​发送模块 
 +always @ (posedge ​pll_1_8m ​or negedge ​rst_n) 
 +begin 
 +    if(!rst_n)
         begin         begin
-            ​if(!rst_n) +            ​tx_cnt ​<= 8'd255
-                begin +            ​tx_r ​<= 1'd1
-                    cycle_cnt ​<= 8'd0+            ​send_over_r ​<= 1'​d0;​ 
-                    ​pwm20_sig_r ​<= 1'd0+        end 
-                    ​pwm50_sig_r ​<= 1'​d0;​ +    else  
-                end +        begin 
-            else +            case(tx_cnt) 
-                begin +                ​8'​d255:​begin 
-                    if(cycle_cnt==cycle-1'​d1)//​对计数器清零,同步两个信号相位+                    if(receive_over)
                         begin                         begin
-                            ​cycle_cnt <= 8'​d0;​ +                            ​tx_cnt ​<= tx_cnt + 1'd1;
-                            pwm20_sig_r <= 1'​d1;​ +
-                            pwm50_sig_r ​<= 1'd1;+
                         end                         end
-                    else if(cycle_cnt==puty_50-1'​d1)//​变换占空比为50%的波形+                    else
                         begin                         begin
-                            ​pwm50_sig_r ​<= 1'​d0;​ +                            ​tx_cnt ​<= tx_cnt;
-                            cycle_cnt <= cycle_cnt + 8'​d1;​ +
-                        end +
-                    else if(cycle_cnt==puty_20-1'​d1)//​变换占空比为20%的波形 +
-                        begin +
-                            pwm20_sig_r <= 1'​d0;​ +
-                            cycle_cnt <= cycle_cnt + 8'​d1;​ +
-                        end +
-                    else//​计数器自加 +
-                        begin +
-                            cycle_cnt <= cycle_cnt + 8'd1;+
                         end                         end
                 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
-        ​end+end 
 +/​*************************************************/​
 </​code>​ </​code>​
 ==== 五、 实验步骤及实验结果 ==== ==== 五、 实验步骤及实验结果 ====
 +{{ :​icore4t:​icore4t_fpga_16_3.jpg?​600 |}}
 +1、将硬件正确连接,如图16.3所示。\\ ​
 +2、将编写好的代码进行编译,并下载到开发板中;\\ ​
 +3、打开串口调试工具,波特率设置为115200,并打开对应端口,如图16.4所示;
 +{{ :​icore4t:​icore4t_fpga_16_4.png?​direct |}}
 +4、在串口调试工具的发送区输入发送数据,FPGA会自动将接收到的数据发送至串口,显示在串口调试工具的接收区,如图16.5所示。
 +{{ :​icore4t:​icore4t_fpga_16_5.png?​direct |}}
 +==== 六、 拓展实验 ====
  
-1、将硬件正确连接,如图11.2所示。 +  * 通过Signaltap观察串口通时序
-{{ :​icore4t:​icore4t_fpga_16_2.jpg?​direct |图16.2}} +
-2、将编写好的代码进行编译,并下载到开发板中; +
-3、观察实验现象——如图11.3所示。 +
-{{ :​icore4t:​icore4t_fpga_16_3.png?​direct |图16.3}} +
- +
-==== 六、 拓展实验 ==== +
-1、改变cycle和puty参数,观察信号变化+
  
icore4tfpga_16.1582682723.txt.gz · 最后更改: 2020/02/26 10:05 由 zgf