FPGA实战 -- UART --- 封装UART IP核

小明 2025-05-07 07:31:01 5

系列文章目录

FPGA基础 – 通信协议 — 了解UART以及电脑串口环境准备

FPGA实战 – UART — 实现串口回环(加FIFO)


文章目录

  • 系列文章目录
  • 前言
  • 一、代码
      • (1)tx
      • (2)rx
      • (3)ctrl
      • (4)fifo.v
      • (5)top
      • 二、IP封装流程
        • (1)创建工程
        • (2)打开 Platform Designer
        • (3)双击New Component
        • (4)修改IP名字
        • (5)添加.v以及头文件
        • (6)引脚分组
          • 1、点击“add interface”添加接口
          • 2、改变接口类型
          • (7)quartus检测IP核
          • 三、调用方法
          • 总结

            前言

            咱们已经学习了UART协议,并且编写了串口回环的代码。每次一些项目遇到串口的时候都要对 RX 或者 TX 代码进行修改,像本人这种非非非非常懒的人,肯定不愿意经常修改代码,所以制作一个IP核会非常方便,只需要调用一下,在top顶层连一连wire就能使用了。简直就是上天赐予的礼物。


            一、代码

            首先创建一个文件夹,记得找一个不会删的地址来创建。因为自己封装的IP核需要Quartus检测这个文档才能使用,所以放在一个不会动的文件夹里比较好。我建议直接放进Quartus的安装文件里。

            这个IP核的代码直接贴在这里,这个代码不用看不用理解不用试验,只需要知道日常IP核的底层代码是咱们看不到的,相当于自己做了一个非常简单的软核。目前市面上有一些专门做IP核的公司,这篇文章做的和这些公司出品的根本比不了,但日常自己使用就已经够了,一些简单的工程项目也可以调用。

            直接创建一个文件夹,建立几个.v文件把代码复制进去就行。

            (1)tx

            //例化模板:
                // uart_tx #(
                //     .CHECK_BIT  ("None"     ),   //"None" 无校验,"Odd" 奇校验,"Even" 偶校验
                //     .BPS        (115200     ),   //UART波特率
                //     .CLK        (50000000   )    //工作时钟
                // )uart_tx_inst(
                //     /* input                */.clk          (clk    ),
                //     /* input                */.rst_n        (rst_n  ),
                //     /* input       [7:0]    */.tx_data      (       ),
                //     /* input                */.tx_data_vld  (       ),
                //     /* output               */.ready        (       ),
                //     /* output  reg          */.tx           (       )
                // );
            module uart_tx #(
                parameter           CHECK_BIT   =   "None"      ,   //"None" 无校验,"Odd" 奇校验,"Even" 偶校验
                parameter           BPS         =   115200      ,   //UART波特率
                parameter           CLK         =   50000000        //工作时钟
                )(
                input               clk             ,
                input               rst_n           ,
                input       [7:0]   tx_data         ,
                input               tx_data_vld     ,
                output              ready           ,
                output  reg         tx              
            );
                parameter       IDLE    =   0,
                                START   =   1,
                                DATA    =   2,
                                CHECK   =   3,
                                STOP    =   4;
                reg     [2:0]   state       ;
                wire            idle2start  ; 
                wire            start2data  ; 
                wire            data2check  ; 
                wire            data2stop   ;
                wire            check2stop  ;
                wire            stop2idle   ; 
                reg	    [12:0]  cnt_bps     ;
                wire		    add_bps_cnt ;
                wire            end_bps_cnt ;	
                parameter       BPS_MAX =   CLK/BPS;        //计算在设定的波特率下,一个bit占用的时钟周期数
                reg	    [3:0]   cnt_bit     ;
                wire		    add_bit_cnt ;
                wire            end_bit_cnt ;	
                reg     [3:0]   bit_max     ;
                reg     [7:0]   tx_data_r   ;
                wire            check_val   ;
            /**************************************************************
                                        状态机   
            **************************************************************/
                always@(posedge clk or negedge rst_n)
                    if(!rst_n)
                        state 
The End
微信