硬件平台:Zedboard

软件环境:Vivado 2015.2

仿真工具:XSIM

//*****************************************************************

1、AXI Uartlite IP核设置

    注意 AXI CLK Frequency = 110MHz

 Image 2.jpg

 

2、Testbench

 在Testbench中,定义了一个状态机,向uartlite写入数据。首先CTRL_REG寄存器写入TX fifo复位命令,接着再向TX fifo中写入要发送的数据。Testbench中例化了一个UART接收模块,用来接收uartlite发送是串行数据并完成串并转换,方便观察。代码如下:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:   
// 
// Create Date: 2016/08/25 14:27:31
// Design Name: 
// Module Name: uartlite
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
 
 
module uartlite();
 
   reg s_axi_aclk;
    reg s_axi_aresetn;
    wire interrupt;
    reg [3 : 0] s_axi_awaddr;
    reg s_axi_awvalid;
    wire s_axi_awready;
    reg [31 : 0] s_axi_wdata;
    reg [3 : 0] s_axi_wstrb;
    reg s_axi_wvalid;
    wire s_axi_wready;
    wire [1 : 0] s_axi_bresp;
    wire s_axi_bvalid;
    reg s_axi_bready ;
    reg [3 : 0] s_axi_araddr;
    reg s_axi_arvalid = 0;
    wire s_axi_arready;
    wire [31 : 0] s_axi_rdata;
    wire [1 : 0] s_axi_rresp;
    wire s_axi_rvalid;
    reg s_axi_rready ;
    reg rx ;
    wire tx;
    
    wire dv;
    wire [7:0] dout;
    //***************************************************************************
    parameter Clockperiod = 9.091; //110M
       
    parameter IDLE = 0;
    parameter SETUP = 1;
    parameter WDATA_WVALID = 2;
    parameter W_WAIT = 3;
    parameter AWADDR_AWVALID = 4;
    parameter AW_WAIT = 5;
    parameter JUDGE_AWREADY = 6;
    parameter INC = 7;
    parameter WAIT_100  = 8;
    
    parameter WAIT_NUM = 10;
    
    reg [7:0] CS = IDLE,NS = IDLE;
    
    
    reg [7:0] wait_cnt = 0;
    
    initial begin
        s_axi_aresetn <= 1’b0;
        #30;
        s_axi_aresetn <= 1’b1;
        s_axi_aclk = 1’b1;
        forever s_axi_aclk = #(Clockperiod/2) ~s_axi_aclk;;
    end
    //
    always@(posedge s_axi_aclk)begin
        CS <= NS;
    end
    //
    always@(*)begin
        case(CS)
            IDLE:           NS = SETUP;
            SETUP:          NS = WDATA_WVALID;
            WDATA_WVALID:   NS = W_WAIT;
            W_WAIT:         NS = AWADDR_AWVALID;
            AWADDR_AWVALID: NS = AW_WAIT;
            AW_WAIT:        NS = JUDGE_AWREADY;
            JUDGE_AWREADY:  begin
                                if(s_axi_awready & s_axi_wready) NS = INC;
                                else NS = JUDGE_AWREADY;
                            end
            INC:            NS = WAIT_100;
            WAIT_100:       begin
                                if(wait_cnt == WAIT_NUM) NS = SETUP;
                                else  NS = WAIT_100;
                            end             
            default:        NS = IDLE;
        endcase
    end
    //
    always@(posedge s_axi_aclk)begin
        if(CS == IDLE)begin
           
            s_axi_awaddr <= 4’hC;
            s_axi_awvalid <= 1’b0;
            s_axi_wdata <= 32’h00000003;
            s_axi_wvalid <= 1’b0;
            s_axi_bready <= 1’b1;
            s_axi_wstrb <= 4’hf;
        end  
    end 
    //
    always@(posedge s_axi_aclk)begin
        if(CS == SETUP)begin
        end
    end
    //
    always@(posedge s_axi_aclk)begin
        if(CS == WDATA_WVALID)begin
            s_axi_wvalid <= 1’b1;
        end            
    end            
    //
    always@(posedge s_axi_aclk)begin
        if(CS == AWADDR_AWVALID)begin
            s_axi_awvalid <= 1’b1; 
        end           
    end
    //   
    always@(posedge s_axi_aclk)begin
        if(CS == JUDGE_AWREADY)begin
            if(s_axi_awready & s_axi_wready) begin
                s_axi_awvalid <= 1’b0;
                s_axi_wvalid <= 1’b0; 
            end
        end
    end   
    always@(posedge s_axi_aclk)begin
        if(CS == INC)begin
            s_axi_awaddr <= 4’h4;
            s_axi_wdata <= s_axi_wdata+1;
        end
    end
    
    always@(posedge s_axi_aclk)begin
        if(CS == WAIT_100)begin
            if(wait_cnt == WAIT_NUM) wait_cnt <= 0;
            else  wait_cnt <= wait_cnt+1;
        end
    end
 
    //****************************************************************************
    //———– Begin Cut here for INSTANTIATION Template —// INST_TAG
    axi_uartlite_0 unt (
        .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
    );
    //**************************************************************************
    //**************************************************************************
 
    UAR_115200 uar_inst(
       .CLK(s_axi_aclk),
       .DI(tx),
       .DV(dv),
       .DO(dout));    
endmodule

3、仿真波形

 

Image 3.jpgImage 4.jpg

Image 5.jpg

    在Testbench中,我们发送的数据为:4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22……

    uar模块输出的数据为:4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,249,243,236,229……

    这是因为TX fifo深度为16,我们向uartlite中写入太快,uartlite来不及发完,因此数丢了。

//*******************************************************

参考资料:


[1]pg142-axi-uartlite.pdf