当前位置: 代码网 > it编程>游戏开发>ar > 【FPGA】xilinx Vivado UART IP核使用

【FPGA】xilinx Vivado UART IP核使用

2024年08月06日 ar 我要评论
xilinx Vivado UART IP核的例化及调用

一.uart通信协议

uart(universal asynchronous receiver/transmitter)串口通信是一种简单的串行通信协议,常用的通信速率9600bite/s、19200bite/s、115200bite/s等,
串口连接图
图中txd:发送数据线;rxd:接收数据线

一个完整的数据帧如下所示。
一个完整数据帧数据传输中接收方rx初始电平为1,当1变为0时候代表起始位,传输数据位以字节为单位,一次只能传输一字节,先发送低位再高位,发送频率由波特率来约定,rx与tx的波特率应该一致。

二.uart ip核使用

1.ip核解读
uart ip核内部框图uart ip核外部接口分别为rx、tx以及interrupt。其中rx为接收端,外部数据经rx控制模块接收数据到rx fifo中,然后通过axi-lite接口将数据读出;tx为发送端,数据经axi-lite接口将发送的数据写入到tx fifo,然后发送到外部接口。我们要做的就是编写axi-lite界面代码,控制ip核的读取及写入,内部数据的串并或并串转换的帧格式如第一章中所示(代码实现可参考后续章节中tx_tb模块以及rx_tb模块)。
uart ip核内部寄存器值若要写入ip核数据,需要先写地址h04,然后再写数据,若要读取外部数据,即rx fifo数据,需要将读取地址写成h00,tx fifo及rx fifo虽然接口为32bit,但是仅低8bit为有效数据,其余为预留。
rx fifotx fifo

同理若想读取ip核状态,需要将读地址改为h08,h08寄存器各个数值代表含义如下图所示。
h08状态寄存器各个数值含义
2.新建工程
3.打开ip核界面,
uart ip核分别选择系统时钟,波特率、传输的数据位宽以及奇偶校验,本次选择时钟100mhz,波特率9600bps,数据位宽8bit,不使用奇偶校验。
4.打开例化文件,如下所示,对ip核进行例化,

axi_uartlite_0 your_instance_name (
  .s_axi_aclk(s_axi_aclk),        // input wire s_axi_aclk
  .s_axi_aresetn(s_axi_aresetn),  // input wire s_axi_aresetn
  .interrupt(interrupt),          // output wire interrupt
  .s_axi_awaddr(s_axi_awaddr),    // input wire [3 : 0] s_axi_awaddr
  .s_axi_awvalid(s_axi_awvalid),  // input wire s_axi_awvalid
  .s_axi_awready(s_axi_awready),  // output wire s_axi_awready
  .s_axi_wdata(s_axi_wdata),      // input wire [31 : 0] s_axi_wdata
  .s_axi_wstrb(s_axi_wstrb),      // input wire [3 : 0] s_axi_wstrb
  .s_axi_wvalid(s_axi_wvalid),    // input wire s_axi_wvalid
  .s_axi_wready(s_axi_wready),    // output wire s_axi_wready
  .s_axi_bresp(s_axi_bresp),      // output wire [1 : 0] s_axi_bresp
  .s_axi_bvalid(s_axi_bvalid),    // output wire s_axi_bvalid
  .s_axi_bready(s_axi_bready),    // input wire s_axi_bready
  .s_axi_araddr(s_axi_araddr),    // input wire [3 : 0] s_axi_araddr
  .s_axi_arvalid(s_axi_arvalid),  // input wire s_axi_arvalid
  .s_axi_arready(s_axi_arready),  // output wire s_axi_arready
  .s_axi_rdata(s_axi_rdata),      // output wire [31 : 0] s_axi_rdata
  .s_axi_rresp(s_axi_rresp),      // output wire [1 : 0] s_axi_rresp
  .s_axi_rvalid(s_axi_rvalid),    // output wire s_axi_rvalid
  .s_axi_rready(s_axi_rready),    // input wire s_axi_rready
  .rx(rx),                        // input wire rx
  .tx(tx)                        // output wire tx
);

vivado中uart ip核采用axi4-lite连接协议,关于axi4协议的说明可以参考我写的这篇文章:

5.生成代码:顶层文件:

module uart_top(

    input m_axi_aclk_100m,
    input m_axi_aresetn,
    input start,
    
    input uart_rx,
    
    output uart_tx

    );
  
  
 
wire interrupt; 

//clock
//wire m_axi_aclk_100m;
//wire m_axi_aresetn;
//write addr        
wire[3:0] m_axi_awaddr;   
wire  m_axi_awvalid; 
wire m_axi_awready;
//write data
wire[31:0] m_axi_wdata;     
wire[3:0]  m_axi_wstrb;     
wire  m_axi_wvalid;    
wire m_axi_wready;
//write response 
wire[1:0] m_axi_bresp;     
wire      m_axi_bvalid;   
wire       m_axi_bready; 
//read addr  
wire[3:0] m_axi_araddr;   
wire      m_axi_arvalid;  
wire     m_axi_arready; 
//read response
wire[31:0] m_axi_rdata;      
wire[1:0]  m_axi_rresp;     
wire m_axi_rvalid;    
wire  m_axi_rready;  
///ststus signal
wire error;
                     
        


m_axi_uartlite_0 u_m_axi_uartlite_0(

.m_axi_aclk(m_axi_aclk_100m),
.m_axi_aresetn(m_axi_aresetn),
//.interrupt(interrupt),
.init_axi_txn(start||interrupt),

//写地址
.m_axi_awaddr(m_axi_awaddr),    // input wire [3 : 0] s_axi_awaddr
.m_axi_awvalid(m_axi_awvalid),  // input wire s_axi_awvalid
.m_axi_awready(m_axi_awready),  // output wire s_axi_awready
//写数据
.m_axi_wdata(m_axi_wdata),      // input wire [31 : 0] s_axi_wdata
.m_axi_wstrb(m_axi_wstrb),      // input wire [3 : 0] s_axi_wstrb,写选通
.m_axi_wvalid(m_axi_wvalid),    // input wire s_axi_wvalid
.m_axi_wready(m_axi_wready),    // output wire s_axi_wready
//写响应
.m_axi_bresp(m_axi_bresp),      // output wire [1 : 0] s_axi_bresp
.m_axi_bvalid(m_axi_bvalid),    // output wire s_axi_bvalid
.m_axi_bready(m_axi_bready),    // input wire s_axi_bready
//读地址
.m_axi_araddr(m_axi_araddr),    // input wire [3 : 0] s_axi_araddr
.m_axi_arvalid(m_axi_arvalid),  // input wire s_axi_arvalid
.m_axi_arready(m_axi_arready),  // output wire s_axi_arready
//读数据
.m_axi_rdata(m_axi_rdata),      // output wire [31 : 0] s_axi_rdata
.m_axi_rresp(m_axi_rresp),      // output wire [1 : 0] s_axi_rresp
.m_axi_rvalid(m_axi_rvalid),    // output wire s_axi_rvalid
.m_axi_rready(m_axi_rready),    // input wire s_axi_rready
.error(error)

    );
 
    


axi_uartlite_0 u_axi_uartlite_0 (
  .s_axi_aclk(m_axi_aclk_100m),        // input wire s_axi_aclk
  .s_axi_aresetn(m_axi_aresetn),  // input wire s_axi_aresetn
  .interrupt(interrupt),          // output wire interrupt
  //写地址
  .s_axi_awaddr(m_axi_awaddr),    // input wire [3 : 0] s_axi_awaddr
  .s_axi_awvalid(m_axi_awvalid),  // input wire s_axi_awvalid
  .s_axi_awready(m_axi_awready),  // output wire s_axi_awready
  //写数据
  .s_axi_wdata(m_axi_wdata),      // input wire [31 : 0] s_axi_wdata
  .s_axi_wstrb(m_axi_wstrb),      // input wire [3 : 0] s_axi_wstrb
  .s_axi_wvalid(m_axi_wvalid),    // input wire s_axi_wvalid
  .s_axi_wready(m_axi_wready),    // output wire s_axi_wready
  //写响应
  .s_axi_bresp(m_axi_bresp),      // output wire [1 : 0] s_axi_bresp
  .s_axi_bvalid(m_axi_bvalid),    // output wire s_axi_bvalid
  .s_axi_bready(m_axi_bready),    // input wire s_axi_bready
  //读地址
  .s_axi_araddr(m_axi_araddr),    // input wire [3 : 0] s_axi_araddr
  .s_axi_arvalid(m_axi_arvalid),  // input wire s_axi_arvalid
  .s_axi_arready(m_axi_arready),  // output wire s_axi_arready
  //读数据
  .s_axi_rdata(m_axi_rdata),      // output wire [31 : 0] s_axi_rdata
  .s_axi_rresp(m_axi_rresp),      // output wire [1 : 0] s_axi_rresp
  .s_axi_rvalid(m_axi_rvalid),    // output wire s_axi_rvalid
  .s_axi_rready(m_axi_rready),    // input wire s_axi_rready
  //对外接口
  .rx(uart_rx),                        // input wire rx
  .tx(uart_tx)                        // output wire tx
);    
 
 
endmodule

其中m_axi_uartlite_0 模块为uart ip提供数据、地址以及读写时序信号,axi-lite的读写时序可以看。

三.仿真

1.方案:方案框图如下所示。
仿真测试方案框图
编写rx_tb模块接收uart ip核的tx数据,观测rx_tb模块中接收到的数据是否与发送一致;编写tx_tb模块发送数据,然后在uart ip核观测接收到数据与tx_tb模块发送的数据是否一致。

2.编写tb代码。将uart ip核、uart_top顶层文件以及uart_rx_tb、uart_tx_tb作为仿真模块,在uart ip核读取数据之前,需要保证ip核内部的rx fifo有数据,所以tx_start 需要早于ip核start。

module uart_top_tb(
    );

parameter freq = 100_000_000;//100mhz
parameter freq_per = 5;//100mhz
parameter c_baudrate = 9600;//
parameter ratio = freq/c_baudrate;//10416
parameter count = ratio/2;//5208

reg sys_clk;
reg rst;
wire s_axi_aclk;
wire s_axi_aresetn;
wire m_axi_aclk_100m;
wire m_axi_aresetn;

wire rxd;
wire[7:0] rx_data    ;
wire rx_data_vld;

wire txd;
wire w_axi_rvalid;
wire start;
wire tx_start;
reg[18:0] cnt_start;
                       
      
initial 
    begin
        sys_clk = 0;
        rst = 1;
        #100;
        rst = 0;           
    end
        
always #freq_per  sys_clk=~sys_clk; //100mhz时钟   

assign s_axi_aclk = sys_clk;
assign s_axi_aresetn = ~rst;


clk_wiz_0 u_clk_wiz_0
 (
  // clock out ports
  .clk_out1(m_axi_aclk_100m),     // output clk_out1
  // status and control signals
  .reset(rst), // input reset
  .locked(m_axi_aresetn),       // output locked
 // clock in ports
  .clk_in1(s_axi_aclk));      // input clk_in1  



always @(posedge m_axi_aclk_100m or negedge m_axi_aresetn)
    if(!m_axi_aresetn)
        cnt_start <= 19'd0;
    else if(cnt_start == 19'd354244)
        cnt_start <= 19'd354244;
    else
        cnt_start <= cnt_start + 1'b1; 

assign start = (cnt_start == 19'd354244)? 1'b1:1'b0;
assign tx_start = (cnt_start == 19'd187588)? 1'b1:1'b0;

uart_rx_tb
#(
    .ratio(ratio),
    .bsp_count(count)
)
 u_uart_rx_tb(
    .clk  (m_axi_aclk_100m)       ,
    .rst_n(m_axi_aresetn)       ,
    
    .rxd(rxd)         ,//接收数据
 
    .rx_data     (rx_data),//串转并后的8bit数据
    .rx_data_vld (rx_data_vld) //串转并后的数据有效标志信号
 
);    

uart_tx_tb 
#(
    .ratio(ratio),
    .bsp_count(count)
)
u_uart_tx_tb(
    .clk  (m_axi_aclk_100m  )      ,
    .rst_n(m_axi_aresetn)      ,
 
    .tx_din    (8'h8a)  ,//数据输入
    .tx_din_vld(tx_start)  ,//数据有效
 
    .txd(txd)
);


uart_top u_uart_top(

    .m_axi_aclk_100m(m_axi_aclk_100m),
    .m_axi_aresetn(m_axi_aresetn),
    .start(start),
    
    .uart_rx(txd),
    .uart_tx(rxd)

    );



   

//axi_uartlite_1 u_axi_uartlite_1 (
//  .s_axi_aclk(s_axi_aclk),        // input wire s_axi_aclk
//  .s_axi_aresetn(s_axi_aresetn),  // input wire s_axi_aresetn
//  .interrupt(interrupt),          // output wire interrupt
//  .s_axi_awaddr(s_axi_awaddr),    // input wire [3 : 0] s_axi_awaddr
//  .s_axi_awvalid(s_axi_awvalid),  // input wire s_axi_awvalid
//  .s_axi_awready(s_axi_awready),  // output wire s_axi_awready
//  .s_axi_wdata(s_axi_wdata),      // input wire [31 : 0] s_axi_wdata
//  .s_axi_wstrb(s_axi_wstrb),      // input wire [3 : 0] s_axi_wstrb
//  .s_axi_wvalid(s_axi_wvalid),    // input wire s_axi_wvalid
//  .s_axi_wready(s_axi_wready),    // output wire s_axi_wready
//  .s_axi_bresp(s_axi_bresp),      // output wire [1 : 0] s_axi_bresp
//  .s_axi_bvalid(s_axi_bvalid),    // output wire s_axi_bvalid
//  .s_axi_bready(s_axi_bready),    // input wire s_axi_bready
//  .s_axi_araddr(s_axi_araddr),    // input wire [3 : 0] s_axi_araddr
//  .s_axi_arvalid(s_axi_arvalid),  // input wire s_axi_arvalid
//  .s_axi_arready(s_axi_arready),  // output wire s_axi_arready
//  .s_axi_rdata(s_axi_rdata),      // output wire [31 : 0] s_axi_rdata
//  .s_axi_rresp(s_axi_rresp),      // output wire [1 : 0] s_axi_rresp
//  .s_axi_rvalid(s_axi_rvalid),    // output wire s_axi_rvalid
//  .s_axi_rready(s_axi_rready),    // input wire s_axi_rready
//  .rx(rx),                        // input wire rx
//  .tx(tx)                        // output wire tx
//);

         
endmodule

3.仿真结果展示:
①ip核写仿真:

ip核写仿真②ip核读仿真
ip核读仿真

总结

uart内容相对基础,注意写好axi-lite接口代码就可以,本文基于vivado软件中uart ip完成了开发。文中罗列了一些基本的概念和设计的流程供大家参考,有问题可联系signal10_d@163.com,资源获取

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com