【FPGA】Vivado UART回环利用ILA IP核实现

目录

一、串口回环的工程框图       

二、Vivado工程的创建

 三、ILA IP核调用


一、串口回环的工程框图       

     

 串口通信协议我发布的UART串口协议博客做了详细的解答,在此不再赘述。

 工程设计思路:

  • 发送数据data给到在图上方的串口发送模块(uart_tx1模块模拟上位机发送发送数据),uart_tx1模块将接收到的data[7:0]进行并串转换成串行数据tx输出;
  • uart_tx1模块输出的串行数据发送给uart模块的子模块(串口接收模块uart_rx);
  • uart_rx模块将接收到的串行数据进行串并转换成并行数据rx_data[7:0]发送给uart模块的另一个子模块(串口接收模块uart_tx);
  • uart_tx模块将接收到的并行数据进行并串转化成串行数据txd并输出。
  • 因为我所用的xilinx芯片是20m的晶振,所以我用pll IP核生成50m的时钟,pll将生成的50m时钟发送给uart_tx1模块和uart模块,确定整个工程是在50m时钟下工作的。

工程代码

uart_top.v

`timescale 1ns / 1psmodule uart_top(input   clk    ,input   rst_n  ,output  clk_50m,output  tx     ,output  txd
);
//参数定义reg [7:0] data   ;reg      data_vid;reg [7:0] cnt    ;wire      add_cnt;wire      end_cnt;//输入的数据dataalways@(posedge clk_50m or negedge rst_n)beginif(~rst_n)begindata <= 0;endelse if(data_vid)begindata <= 8'ha0;endendalways@(posedge clk_50m or negedge rst_n)beginif(~rst_n)begincnt <= 0 ;endelse if(add_cnt)beginif(end_cnt)begincnt <= 0;endelse begincnt <= cnt +1 ;endendendassign add_cnt = 1;assign end_cnt = add_cnt &(cnt == 5 - 1);
//输入的数据使能always@(posedge clk_50m or negedge rst_n)beginif(~rst_n)begindata_vid <= 0;endelse if(end_cnt)begindata_vid <= 1 ;endend
//模块例化clk_wiz_0 instance_name(// Clock out ports.clk_50m(clk_50m),     // output clk_50m// Status and control signals.reset  (~rst_n ), // input reset.locked (locked ),       // output locked// Clock in ports.clk_20m(clk    )); 
//串口发送模块模拟上位机发送数据uart_tx u_uart_tx(.clk              (clk_50m  ),.rst_n            (rst_n    ),.tx_din           (data     ),.tx_din_vld       (data_vid ),.txd              (tx       ));
//串口模块uart  u_uart(.clk          (clk_50m ),.rst_n        (rst_n   ),// .clk_50m     (clk_50m),.rxd          (tx      ),.txd          (txd     ));
//ila IP例化
ila_0 your_instance_name (.clk(clk_50m), // input wire clk.probe0(cnt   ), // input wire [7:0]  probe0  .probe1(data  ), // input wire [7:0]  probe1 .probe2(tx    ), // input wire [0:0]  probe2 .probe3(txd   )  // input wire [0:0]  probe3
);endmodule

uart模块的顶层uart.v

`timescale 1ns / 1psmodule uart(input       clk     ,input       rst_n   ,input       rxd     ,output      txd
);
//参数定义
wire    [7:0]   rx_data     ;
wire            rx_data_vld ;
//模块例化
uart_tx u_uart_tx(.clk             (clk          ),              .rst_n           (rst_n        ),  .tx_din          (rx_data      ),      .tx_din_vld      (rx_data_vld  ),          .txd             (txd          )  
);uart_rx u_uart_rx(
.clk           ( clk            ),
.rst_n         (  rst_n         ),
.rxd           (rxd             ),
.rx_data       (  rx_data       ),  
.rx_data_vld   (  rx_data_vld   ) 
);endmodule

uart模块的子模块串口接收模块uart_rx.v

`timescale 1ns / 1psmodule uart_rx(input               clk         ,input               rst_n       ,input               rxd         ,//接收数据output reg [7:0]    rx_data     ,//串转并后的8bit数据output  reg         rx_data_vld  //串转并后的数据有效标志信号);
//参数定义
parameter   bps_value = 868 ; //信号定义
reg         rx_r0   ;
reg         rx_r1   ;wire        nedge   ;//起始位reg         flag    ;//接收标志reg [12:0]  cnt_bps     ;
wire        add_cnt_bps ;
wire        end_cnt_bps ;reg [3:0]   cnt_bit     ;
wire        add_cnt_bit ;
wire        end_cnt_bit ;reg [9:0]   data_in     ;//串行转换//插入两级寄存器进行数据同步,消除亚稳态always @(posedge clk or negedge rst_n) beginif(!rst_n)beginrx_r0 <= 1'b1;rx_r1 <= 1'b1;end else beginrx_r0 <= rxd;rx_r1 <= rx_r0;endendassign nedge = rx_r1 & ~rx_r0;//检测到下降沿传输信号拉高always @(posedge clk or negedge rst_n) beginif(!rst_n)beginflag <= 0;endelse if(nedge)beginflag <= 1;endelse if(end_cnt_bit)beginflag <= 0;endend//波特率计数器开始计数always @(posedge clk or negedge rst_n) beginif(!rst_n)begincnt_bps <= 0;endelse if(add_cnt_bps)beginif(end_cnt_bps)begincnt_bps <= 0;endelse begincnt_bps <= cnt_bps + 1;endend else begincnt_bps <= cnt_bps;endendassign add_cnt_bps = flag;assign end_cnt_bps = add_cnt_bps && cnt_bps == bps_value-1;//比特率开始计数always @(posedge clk or negedge rst_n) beginif(!rst_n)begincnt_bit <= 0;endelse if(add_cnt_bit)beginif(end_cnt_bit)begincnt_bit <= 0;endelse begincnt_bit <= cnt_bit +1;endendelse begincnt_bit <= cnt_bit;endendassign add_cnt_bit = end_cnt_bps;assign end_cnt_bit = add_cnt_bit && (cnt_bit == (10-1)|| data_in[0]);always @(posedge clk or negedge rst_n) beginif(!rst_n)begindata_in <= 0;endelse if(flag)beginif(cnt_bps == (bps_value >> 1))begindata_in[cnt_bit] <= rx_r1;endendendalways @(posedge clk or negedge rst_n) beginif(!rst_n)beginrx_data <= 0;endelse if(end_cnt_bit)beginrx_data <= data_in[8:1];endelse beginrx_data <= 0;endendalways @(posedge clk or negedge rst_n) beginif(!rst_n)beginrx_data_vld <= 0;endelse if(end_cnt_bit && data_in[0]==0)beginrx_data_vld <= 1'b1;endelse beginrx_data_vld <= 0;endend
endmodule

uart模块的子模块串口发送模块uart_tx.v

`timescale 1ns / 1ps
module uart_tx(input       clk         ,input       rst_n       ,input [7:0] tx_din      ,//数据输入input       tx_din_vld  ,//数据有效output reg  txd
);//参数定义parameter  bps_value = 868;//57600//信号定义reg [9:0]   tx_data     ;//锁存要发送的数据,数据帧格式reg [9:0]   cnt_bps     ;//波特率计数器wire        add_cnt_bps ;wire        end_cnt_bps ;reg [4:0]   cnt_bit     ;//比特率计数器wire        add_cnt_bit ;wire        end_cnt_bit ;reg         flag        ;//计数标志,开始传输标志always @(posedge clk or negedge rst_n) beginif(!rst_n)begintx_data <= 1'b1;endelse if(tx_din_vld)begintx_data <= {1'b1,tx_din,1'b0};//数据有效,将起始位,数据位和停止位拼接endendalways @(posedge clk  or negedge rst_n) beginif(!rst_n)beginflag <= 1'b0;endelse if(tx_din_vld)begin//波特计数器开启条件flag <= 1'b1;endelse if(end_cnt_bit)beginflag <= 1'b0;endendalways @(posedge clk  or negedge rst_n) beginif(!rst_n)begincnt_bps <= 0;endelse if(add_cnt_bps)beginif(end_cnt_bps)begincnt_bps <= 0;endelse begincnt_bps <= cnt_bps + 1 ;endendelse begincnt_bps <= cnt_bps;endendassign add_cnt_bps = flag;assign end_cnt_bps = add_cnt_bps && (cnt_bps == bps_value - 1);//波特率计数器结束条件always @(posedge clk or negedge rst_n) beginif(!rst_n)begincnt_bit <= 0;endelse if(add_cnt_bit)beginif(end_cnt_bit)begincnt_bit <= 0;endelse begincnt_bit <= cnt_bit + 1;endendelse begincnt_bit <= cnt_bit;endendassign add_cnt_bit = end_cnt_bps;assign end_cnt_bit = add_cnt_bit && (cnt_bit == 10-1);always @(posedge clk or negedge rst_n) beginif(!rst_n)begintxd <= 1 ;endelse if(flag)begintxd <= tx_data[cnt_bit];//并行数据转为串行数据endelse begintxd <= 1;endendendmodule

二、Vivado工程的创建

    工程的创建我发布的Vivado软件使用教程博客做了详细的介绍,包括:   

  1. 创建工程并文本输入
  2. 添加设计文件
  3. 管脚约束和时序约束
  4. 生成bit文件

再此也不再赘述。

下图是我创建的工程。

 三、ILA IP核调用

    工程创建并添加设计文件完成后,经过管脚约束和时序约束,生成bit文件后连接板子。因为调用ILA IP核需要连接板子才能抓出波形。

     1、将板子连接电源,接着将板子和电脑用下载器连接之后,点击下图的Auto Connect按钮,显示出连接的芯片xc7a200t。

     

 2、配置 ILA ip核

  在 IP  Catalog 界面搜索 ila,点击搜索出的ILA。

    由于要采样4个信号,Probes的数量设置为4,Sample Data Depth指的是采样深度,设置的越高,采集的信号越多,同样消耗的资源也会越多。

 在Probe_Ports页面,设置Probe的宽度,设置PROBE0和PROBE1位宽为8,用于采样cnt和输入的data,设置PROBE2和PROBE3位宽为1,用于采样tx和txd。点击OK。

 3、例化IP

在uart_top.v中例化ila,并保存。

 4、点击Generate Bitstream重新生成Bitstream文件,生成完成后,开始下载程序。

 这时候看到有bit和ltx文件,点击program。

 此时弹出在线调试窗口,出现了我们添加的信号。

 由上图可以看到:

  • uart_tx1模块模拟上位机将接收到的并行数据data[7:0]并串转换为串行数据tx发送给uart模块;
  • uart模块内部的子模块uart_rx将接收到的串行数据tx通过串并转换为并行数据,另一个子模块uart_tx通过并串转换将并行数据转换为串行数据txd输出。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部