回答

收藏

[评测分享] 【超越者Spartan-6 FPGA开发板】 + 串口输出

#板卡评测 #板卡评测 2620 人阅读 | 0 人回复 | 2021-05-27

   
    来学习下超越者Spartan-6 FPGA的串口通信。
    实现的功能:将FPGA计数的值通过串口输出。

    一、硬件
   
    测试使用COM2口来输出数据
   

    将P1的跳线帽选择U2_RX和U2_TX,选择到COM2口上
   

     串口2使用的FPGA引脚。


    二、软件部分

     2.1、计数器部分程序

     定时0.5S,变量txjs_data+1,同时将使能信号传送给串口。

  1. module txjs(
  2.          input                 sys_clk,                   //系统时钟
  3.     input            sys_rst_n,                 //系统复位,低电平有效   
  4.     output reg       txjs_en,                   //发送使能信号
  5.     output reg [7:0] txjs_data                  //待发送数据
  6.     );
  7.          
  8.         reg [23:0] counter;
  9.        
  10.         //计数器对系统时钟计数,计时0.5秒
  11. always @(posedge sys_clk or negedge sys_rst_n)
  12. begin
  13.     if (!sys_rst_n)
  14.         counter <= 24'd0;
  15.     else if (counter < 24'd2500_0000)
  16.         counter <= counter + 1'b1;
  17.     else
  18.         counter <= 24'd0;
  19. end

  20. always @(posedge sys_clk or negedge sys_rst_n)
  21. begin
  22.     if (!sys_rst_n)
  23.                 begin
  24.         txjs_data <= 4'd0;
  25.                   txjs_en <= 1;
  26.                  end
  27.     else if(counter == 24'd2500_0000)
  28.                 begin
  29.         txjs_data <= txjs_data+1;
  30.        
  31.                   txjs_en <= 1;
  32.                 end
  33.     else
  34.                 begin
  35.         txjs_data <= txjs_data;
  36.                   txjs_en <= 0;
  37.                 end
  38. end

  39. endmodule
复制代码

    2.2、串口发送部分程序
  1. //****************************************Copyright (c)***********************************//
  2. //原子哥在线教学平台:www.yuanzige.com
  3. //技术支持:www.openedv.com
  4. //淘宝店铺:http://openedv.taobao.com
  5. //关注微信公众平台微信号:"正点原子",免费获取ZYNQ & FPGA & STM32 & LINUX资料。
  6. //版权所有,盗版必究。
  7. //Copyright(C) 正点原子 2018-2028
  8. //All rights reserved                                       
  9. //----------------------------------------------------------------------------------------
  10. // File name:           uart_send
  11. // Last modified Date:  2019/10/9 10:07:36
  12. // Last Version:        V1.1
  13. // Descriptions:        UART串口发送模块
  14. //----------------------------------------------------------------------------------------
  15. // Created by:          正点原子
  16. // Created date:        2019/10/9 10:07:36
  17. // Version:             V1.0
  18. // Descriptions:        The original version
  19. //
  20. //----------------------------------------------------------------------------------------
  21. //****************************************************************************************//

  22. module uart_send(
  23.     input              sys_clk,                  //系统时钟
  24.     input         sys_rst_n,                //系统复位,低电平有效
  25.    
  26.     input         uart_en,                  //发送使能信号
  27.     input  [7:0]  uart_din,                 //待发送数据
  28.     output        uart_tx_busy,             //发送忙状态标志
  29.     output        en_flag     ,
  30.     output  reg   tx_flag,                  //发送过程标志信号
  31.     output  reg [ 7:0] tx_data,             //寄存发送数据
  32.     output  reg [ 3:0] tx_cnt,              //发送数据计数器
  33.     output  reg   uart_txd                  //UART发送端口
  34.     );
  35.    
  36. //parameter define
  37. parameter  CLK_FREQ = 50000000;                    //系统时钟频率
  38. parameter  UART_BPS = 9600;                        //串口波特率
  39. localparam  BPS_CNT  = CLK_FREQ/UART_BPS;           //为得到指定波特率,对系统时钟计数BPS_CNT次

  40. //reg define
  41. reg        uart_en_d0;
  42. reg        uart_en_d1;  
  43. reg [15:0] clk_cnt;                           //系统时钟计数器

  44. //wire define
  45. wire       en_flag;

  46. //*****************************************************
  47. //**                    main code
  48. //*****************************************************
  49. //在串口发送过程中给出忙状态标志
  50. assign uart_tx_busy = tx_flag;

  51. //捕获uart_en上升沿,得到一个时钟周期的脉冲信号
  52. assign en_flag = (~uart_en_d1) & uart_en_d0;

  53. //对发送使能信号uart_en延迟两个时钟周期
  54. always @(posedge sys_clk or negedge sys_rst_n)
  55. begin         
  56.     if (!sys_rst_n)
  57.                 begin
  58.         uart_en_d0 <= 1'b0;                                 
  59.         uart_en_d1 <= 1'b0;
  60.                 end                                                      
  61.     else
  62.                 begin                                               
  63.         uart_en_d0 <= uart_en;                              
  64.         uart_en_d1 <= uart_en_d0;                           
  65.                 end
  66. end


  67. //当脉冲信号en_flag到达时,寄存待发送的数据,并进入发送过程         
  68. always @(posedge sys_clk or negedge sys_rst_n)
  69. begin         
  70.         if (!sys_rst_n)
  71.                 begin                                 
  72.         tx_flag <= 1'b0;
  73.         tx_data <= 8'd0;
  74.                 end
  75.          
  76.         else if (en_flag)                                 //检测到发送使能上升沿   
  77.                 begin                                    
  78.         tx_flag <= 1'b1;                //进入发送过程,标志位tx_flag拉高
  79.         tx_data <= uart_din;            //寄存待发送的数据
  80.                 end
  81.                                             //计数到停止位结束时,停止发送过程
  82.         else if ((tx_cnt == 4'd9) && (clk_cnt == BPS_CNT - (BPS_CNT/16)))
  83.                 begin                                       
  84.                         tx_flag <= 1'b0;                //发送过程结束,标志位tx_flag拉低
  85.                         tx_data <= 8'd0;
  86.                 end
  87.         
  88.         else
  89.                 begin
  90.             tx_flag <= tx_flag;
  91.             tx_data <= tx_data;
  92.                 end
  93. end

  94. //进入发送过程后,启动系统时钟计数器
  95. always @(posedge sys_clk or negedge sys_rst_n)
  96. begin         
  97.         if (!sys_rst_n)                             
  98.                 clk_cnt <= 16'd0;
  99.                
  100.         else if (tx_flag)                                                                 //处于发送过程
  101.                 begin                 
  102.         if (clk_cnt < BPS_CNT - 1)
  103.             clk_cnt <= clk_cnt + 1'b1;
  104.         else
  105.             clk_cnt <= 16'd0;                       //对系统时钟计数达一个波特率周期后清零
  106.     end
  107.     else                             
  108.         clk_cnt <= 16'd0;                                                     //发送过程结束
  109. end

  110. //进入发送过程后,启动发送数据计数器
  111. always @(posedge sys_clk or negedge sys_rst_n)
  112. begin         
  113.     if (!sys_rst_n)                             
  114.         tx_cnt <= 4'd0;
  115.     else if (tx_flag)                                                         //处于发送过程
  116.                 begin                 
  117.         if (clk_cnt == BPS_CNT - 1)                        //对系统时钟计数达一个波特率周期
  118.             tx_cnt <= tx_cnt + 1'b1;                //此时发送数据计数器加1
  119.         else
  120.             tx_cnt <= tx_cnt;      
  121.                 end
  122.     else                              
  123.         tx_cnt  <= 4'd0;                                            //发送过程结束
  124. end

  125. //根据发送数据计数器来给uart发送端口赋值
  126. always @(posedge sys_clk or negedge sys_rst_n)
  127. begin        
  128.     if (!sys_rst_n)  
  129.         uart_txd <= 1'b1;        
  130.     else if (tx_flag)
  131.         case(tx_cnt)
  132.             4'd0: uart_txd <= 1'b0;         //起始位
  133.             4'd1: uart_txd <= tx_data[0];   //数据位最低位
  134.             4'd2: uart_txd <= tx_data[1];
  135.             4'd3: uart_txd <= tx_data[2];
  136.             4'd4: uart_txd <= tx_data[3];
  137.             4'd5: uart_txd <= tx_data[4];
  138.             4'd6: uart_txd <= tx_data[5];
  139.             4'd7: uart_txd <= tx_data[6];
  140.             4'd8: uart_txd <= tx_data[7];   //数据位最高位
  141.             4'd9: uart_txd <= 1'b1;         //停止位
  142.             default: ;
  143.         endcase
  144.     else
  145.         uart_txd <= 1'b1;                   //空闲时发送端口为高电平
  146. end

  147. endmodule                  
复制代码

     2.3、主程序
  1. module uart_top_rs232(
  2.     input           sys_clk,            //外部50M时钟
  3.     input           sys_rst_n,          //外部复位信号,低有效

  4.     input           uart_rxd,           //UART接收端口
  5.     output          uart_txd            //UART发送端口
  6.     );

  7. //parameter define
  8. parameter  CLK_FREQ = 50000000;         //定义系统时钟频率
  9. parameter  UART_BPS = 115200;           //定义串口波特率
  10.    
  11. //wire define   
  12. wire       uart_recv_done;              //UART接收完成
  13. wire [7:0] uart_recv_data;              //UART接收数据
  14. wire       uart_send_en;                //UART发送使能
  15. wire [7:0] uart_send_data;              //UART发送数据
  16. wire       uart_tx_busy;                //UART发送忙状态标志



  17. //*****************************************************
  18. //**                    main code
  19. //*****************************************************

  20. //串口发送模块   
  21. uart_send #(                          
  22.     .CLK_FREQ       (CLK_FREQ),         //设置系统时钟频率
  23.     .UART_BPS       (UART_BPS))         //设置串口发送波特率
  24. u_uart_send(                 
  25.     .sys_clk        (sys_clk),
  26.     .sys_rst_n      (sys_rst_n),
  27.      
  28.     .uart_en        (uart_send_en),  
  29.     .uart_din       (uart_send_data),
  30.     .uart_tx_busy   (uart_tx_busy),
  31.     .uart_txd       (uart_txd)
  32.     );

  33. txjs u_txjs(
  34.         .sys_clk        (sys_clk),            
  35.         .sys_rst_n      (sys_rst_n),  
  36.         .txjs_en        (uart_send_en),     //发送使能信号
  37.         .txjs_data      (uart_send_data)    //待发送数据       
  38. );
  39.   
  40. endmodule
复制代码

    三、运行程序


    0.5S间隔,串口输出计数值。
   

     
   
分享到:
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条