【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软件使用教程博客做了详细的介绍,包括:
- 创建工程并文本输入
- 添加设计文件
- 管脚约束和时序约束
- 生成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输出。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
