zoukankan      html  css  js  c++  java
  • 使用Xilinx UART-LITE IP实现串口--逻辑代码实现

    `timescale 1ns / 1ps
    //////////////////////////////////////////////////////////////////////////////////
    // Company: 
    // Engineer: 
    // 
    // Create Date: 2019/01/10 21:13:43
    // Design Name: 
    // Module Name: uart_top
    // Project Name: 
    // Target Devices: 
    // Tool Versions: 
    // Description: 
    // 
    // Dependencies: 
    // 
    // Revision:
    // Revision 0.01 - File Created
    // Additional Comments:
    // 
    //////////////////////////////////////////////////////////////////////////////////
    
    
    module uart_top(
        input CLK100MHZ,
          input ck_rst,
        output tx,
        input rx,
        output led
        );
        
        localparam COUNT_5MS = 28'h2_FA_F0_7F;//100M  500ms
     //闪灯指示   
        reg [27:0]r_count = 28'h0;
        reg r_led = 1'b0;
        always @ (posedge CLK100MHZ)
        begin
            if(r_count >= COUNT_5MS) begin
                r_count <= 28'h0;
                r_led <= ~r_led;
            end
            else begin
                r_count <= r_count +1'b1;
                r_led <= r_led;
            end
        end
        assign led = r_led;
        
        
      wire w_uart_rstn;
      (*MARK_DEBUG = "TRUE"*)wire w_uart_int;
        (*MARK_DEBUG = "TRUE"*)reg [3:0]s_axi_awaddr;
        (*MARK_DEBUG = "TRUE"*)reg s_axi_awvalid;
        (*MARK_DEBUG = "TRUE"*)wire s_axi_awready;
        (*MARK_DEBUG = "TRUE"*)reg [31:0]s_axi_wdata;
        (*MARK_DEBUG = "TRUE"*)reg [3:0]s_axi_wstrb;
        (*MARK_DEBUG = "TRUE"*)reg s_axi_wvalid = 1'b0;
        (*MARK_DEBUG = "TRUE"*)wire s_axi_wready;
        (*MARK_DEBUG = "TRUE"*)wire [1:0]s_axi_bresp;
        (*MARK_DEBUG = "TRUE"*)wire s_axi_bvalid;
        (*MARK_DEBUG = "TRUE"*)reg s_axi_bready = 1'b0;
        (*MARK_DEBUG = "TRUE"*)reg [3:0]s_axi_araddr = 4'h0;
        (*MARK_DEBUG = "TRUE"*)reg s_axi_arvalid = 1'b0;
        (*MARK_DEBUG = "TRUE"*)wire s_axi_arready;//Read ready. This signal indicates that the master can accept the read data and response information.
        (*MARK_DEBUG = "TRUE"*)wire [31:0]s_axi_rdata;
        (*MARK_DEBUG = "TRUE"*)wire [1:0]s_axi_rresp;
        wire s_axi_rvalid;
        (*MARK_DEBUG = "TRUE"*)reg s_axi_rready = 1'b0;
        axi_uartlite_0 uart_lite
         (
            .s_axi_aclk(CLK100MHZ),
            .s_axi_aresetn(ck_rst),
            
            .interrupt(w_uart_int),
            .s_axi_awaddr(s_axi_awaddr),// : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
            .s_axi_awvalid(s_axi_awvalid),// : IN STD_LOGIC;
            .s_axi_awready(s_axi_awready),// : OUT STD_LOGIC;
            .s_axi_wdata(s_axi_wdata),// : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
            .s_axi_wstrb(s_axi_wstrb),// : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
            .s_axi_wvalid(s_axi_wvalid),// : IN STD_LOGIC;
            .s_axi_wready(s_axi_wready),// : OUT STD_LOGIC;
            .s_axi_bresp(s_axi_bresp),// : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
            .s_axi_bvalid(s_axi_bvalid),// : OUT STD_LOGIC;
            .s_axi_bready(s_axi_bready),// : IN STD_LOGIC;
            .s_axi_araddr(s_axi_araddr),// : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
            .s_axi_arvalid(s_axi_arvalid),//: IN STD_LOGIC;
            .s_axi_arready(s_axi_arready),//: OUT STD_LOGIC;
            .s_axi_rdata(s_axi_rdata),// : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
            .s_axi_rresp(s_axi_rresp),// : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
            .s_axi_rvalid(s_axi_rvalid),// : OUT STD_LOGIC;
            .s_axi_rready(s_axi_rready),// : IN STD_LOGIC;
            
            .rx(rx),// : IN STD_LOGIC;
            .tx(tx)// : OUT STD_LOGIC
          );
        //debug  
        wire begin_init;
        reg [31:0]r_receive_data;
        vio_0 debug(
            .clk(CLK100MHZ),
            .probe_in0(r_receive_data),
            .probe_out0(begin_init)
        );
    //receive data to fifo
    (*MARK_DEBUG = "TRUE"*)wire [9:0]  data_count;//8 bit count
    (*MARK_DEBUG = "TRUE"*)wire [7:0]w_receive_data;
    wire fifo_empty;
    fifo_generator_0 receive_fifo
     (
        .clk(CLK100MHZ),// : IN STD_LOGIC;
        .srst(~ck_rst),// : IN STD_LOGIC;
        .din(s_axi_rdata[7:0]),// : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
        .wr_en(s_axi_rvalid & (state == 8'b00000100)),// : IN STD_LOGIC;
        .rd_en(r_Read_en),// : IN STD_LOGIC;
        .dout(w_receive_data),// : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
        .full(),// : OUT STD_LOGIC;
        .almost_full(),// : OUT STD_LOGIC;
        .empty(fifo_empty),// : OUT STD_LOGIC;
        .almost_empty(),// : OUT STD_LOGIC;
        .data_count(data_count)// : OUT STD_LOGIC_VECTOR(9 DOWNTO 0)
      );
        
          
       parameter IDLE  = 8'b00000001;
       parameter INIT  = 8'b00000010;
       parameter RECIVE  = 8'b00000100;
       parameter T_R_IDLE  = 8'b00001000;
       parameter RECEIVE  = 8'b00010000;
       parameter CHECK_STA  = 8'b00100000;
       parameter state7  = 8'b01000000;
       parameter state8  = 8'b10000000;
    
       (*MARK_DEBUG = "TRUE"*)reg [7:0] state = IDLE;
       (*MARK_DEBUG = "TRUE"*)reg [7:0]cnt = 8'h00;
    
       always @(posedge CLK100MHZ)
          if (~ck_rst) begin
             state  <= IDLE;
          end
          else
             case (state)
                IDLE : begin
                   if (begin_init)
                      state <= INIT;
                   else if (w_uart_int)
                      state <= RECIVE;
                   else
                      state <= IDLE;
                end
                INIT : begin//向0xC写入0x1F,使能中断,清空W/R FIFO
                   if (s_axi_bvalid && (s_axi_bresp == 2'b00))
                        state <= CHECK_STA;
                   else
                      state <= INIT;
                end
                RECIVE : begin
                   if (s_axi_rvalid) begin
                      state <= CHECK_STA;
                      r_receive_data <= s_axi_rdata;
                   end   
                   else begin
                      state <= RECIVE;
                      r_receive_data <= r_receive_data;
                   end
                end
    
                CHECK_STA : begin//检查状态寄存器
                   if (s_axi_rvalid & s_axi_rdata[0])//receive buf is not empt
                      state <= RECIVE;
                   else
                      state <= CHECK_STA;
                end
                default:begin
                    
                end
            endcase
            
            
            reg [7:0]r_state;
        always @ (posedge CLK100MHZ)
                r_state <= state;
        
        always @ (posedge CLK100MHZ) begin
            if(~ck_rst) begin
                cnt <= 8'h00;
            end
            else begin
                case(state)
                    RECIVE :begin
                        if(s_axi_rvalid | (cnt>8'h4))
                            cnt <= 8'h00;
                        else
                            cnt <= cnt +1'b1;
                    end
                    CHECK_STA :begin
                        if((s_axi_rvalid & s_axi_rdata[0]) | (cnt>8'h4))
                            cnt <= 8'h00;
                        else
                            cnt <= cnt +1'b1;
                    end        
                    default:begin
                        cnt <= 8'h00;
                    end
                endcase
                
            end
        end
        
            
        always @ (posedge CLK100MHZ)
        begin
            case(state)
                IDLE:begin
                    s_axi_awaddr <=4'h0;
                    s_axi_wdata <= 32'h00_00_00_00;
                    s_axi_wstrb <= 4'h0;
                    s_axi_arvalid <= 1'b0;
                    if(begin_init) begin
                        s_axi_awvalid <= 1'b1;
                        s_axi_wvalid <= 1'b1;
                    end
                    else begin
                        s_axi_awvalid <= 1'b0;
                        s_axi_wvalid <= 1'b0;
                    end
                end
                INIT:begin    
                    if(s_axi_wready) begin
                        s_axi_bready <= 1'b1;
                        s_axi_awvalid <= 1'b0;
                        s_axi_wvalid <= 1'b0;    
                    end        
                    else begin
                        s_axi_bready <= 1'b0;
                        
                        s_axi_awaddr <=4'hc;
                      s_axi_awvalid <= s_axi_awvalid;
                      s_axi_wdata <= 32'h1f;
                      s_axi_wstrb <= 4'hf;
                      s_axi_wvalid <= s_axi_wvalid;    
                    end
                end
                RECIVE:begin
                    if(cnt > 8'h3) begin
                        s_axi_arvalid <= 1'b0;
                    end
                    else if(cnt > 8'h2) begin
                        s_axi_arvalid <= 1'b1;
                    end
                    else if(cnt > 8'h1) begin
                        s_axi_araddr <=4'h0;
                        s_axi_rready <= 1'b1;
                    end
                    else begin
                     s_axi_rready <= 1'b1;
                    end
                end
                CHECK_STA:begin
                    if(cnt > 8'h3) begin
                        s_axi_arvalid <= 1'b0;
                    end
                    else if(cnt > 8'h2) begin
                        s_axi_arvalid <= 1'b1;
                    end
                    else if(cnt > 8'h1) begin
                        s_axi_araddr <=4'h8;
                        s_axi_rready <= 1'b1;
                    end
                    else begin
                     s_axi_rready <= 1'b1;
                    end
                end
                default:begin
                    s_axi_awaddr <=4'h0;
                    s_axi_awvalid <= 1'b0;
                    s_axi_wdata <= 32'h00_00_00_00;
                    s_axi_wstrb <= 4'h0;
                    s_axi_wvalid <= 1'b0;
                    
                    s_axi_arvalid <= 1'b0;
                end
            endcase
        end
        //read FIFO,unpack
        //如果读到2F,开始计数,再读11个字节,并相加,若和的最后一个字节为00,这是一个完整包,否则丢掉重新找2F
            
         parameter IDLE_P       = 4'b0001;
       parameter FIRST_BYTE   = 4'b0010;
       parameter RECEIVE_PACK = 4'b0100;
       parameter CHECK_PACK   = 4'b1000;
    
       (*MARK_DEBUG = "TRUE"*)reg [3:0] state_pack = IDLE_P;
         (*MARK_DEBUG = "TRUE"*)reg [3:0] r_Byte_cnt = 4'h0;
       always @(posedge CLK100MHZ)
          if (~ck_rst) begin
             state_pack <= IDLE_P;
           end
          else
             case (state_pack)
               IDLE_P : begin
                   if (r_Read_en)
                      state_pack <= FIRST_BYTE;
                   else
                      state_pack <= IDLE_P;
                end
                FIRST_BYTE : begin
                   if (w_receive_data == 8'h2f)//check pack header
                      state_pack <= RECEIVE_PACK;
                   else
                      state_pack <= IDLE_P;;
                end
                RECEIVE_PACK : begin
                   if (r_Byte_cnt == 4'hb)//
                      state_pack <= CHECK_PACK;
                   else
                      state_pack <= RECEIVE_PACK;
                end
                CHECK_PACK : begin
                   if (pack_check_done)//no matter success or failed
                       state_pack <= IDLE_P;
                   else
                      state_pack <= CHECK_PACK;
                end
                default : begin  // Fault Recovery
                   state_pack <= IDLE_P;
                end
             endcase
        
        reg r_Read_en = 1'b0;
        reg [7:0]buf_data[0:11];  
        reg pack_check_done = 1'b0; 
        (*MARK_DEBUG = "TRUE"*)reg check_success = 1'b0;  
        always @ (posedge CLK100MHZ) begin
            if(~ck_rst) begin
                r_Read_en <= 1'b0;
                r_Byte_cnt <= 4'h0;
                pack_check_done <= 1'b0;
                check_success <= 1'b0;
            end
            else begin
                case(state_pack)
                    IDLE_P:begin
                        check_success <= 1'b0;
                        r_Byte_cnt <= 4'h0;
                        pack_check_done <= 1'b0;
                        if(rr_fifo_empty & (~fifo_empty)) begin
                            r_Read_en <= 1'b1;
                        end
                        else begin
                            r_Read_en <= 1'b0;
                        end
                    end
                    FIRST_BYTE:begin//do nothing
                                r_Read_en <= 1'b0;
                    end
                    RECEIVE_PACK:begin
                        if(rr_fifo_empty & (~fifo_empty))begin
                            r_Byte_cnt <= r_Byte_cnt + 1'b1;
                            r_Read_en <= 1'b1;
                        end
                        else begin
                            r_Byte_cnt <= r_Byte_cnt;
                            r_Read_en <= 1'b0;
                        end
                    end
                    CHECK_PACK:begin
                        pack_check_done <= 1'b1;
                        if(data_check[7:0] == 8'h00) begin
                            check_success <= 1'b1;
                        end
                        else begin
                            check_success <= 1'b0;
                        end
                    end
                    default:begin
                        
                    end
                endcase
            end
        end
        
        reg rr_fifo_empty;
        reg rr_Read_en;
        always @ (posedge CLK100MHZ) begin
            rr_fifo_empty <= fifo_empty;
            rr_Read_en <= r_Read_en;
        end
        
        //data check and buff
        (*MARK_DEBUG = "TRUE"*)reg [31:0]data_check = 32'h0000002f;
        always @ (posedge CLK100MHZ) begin
            if(state_pack == IDLE_P) begin
                data_check <= 32'h0000002f;
            end
            else if((state_pack > FIRST_BYTE) & (rr_Read_en)) begin
                buf_data[r_Byte_cnt] <= w_receive_data;
                data_check <= data_check+w_receive_data;
            end
            else begin
                data_check <= data_check;
            end
        end
        
        (*MARK_DEBUG = "TRUE"*)reg [7:0]r_checded_data[1:10];
            always @ (posedge CLK100MHZ) begin
                if(check_success) begin
                    r_checded_data[1] <=  buf_data[1];
                    r_checded_data[2] <=  buf_data[2];
                    r_checded_data[3] <=  buf_data[3];
                    r_checded_data[4] <=  buf_data[4];
                    r_checded_data[5] <=  buf_data[5];
                    r_checded_data[6] <=  buf_data[6];
                    r_checded_data[7] <=  buf_data[7];
                    r_checded_data[8] <=  buf_data[8];
                    r_checded_data[9] <=  buf_data[9];
                    r_checded_data[10] <=  buf_data[10];
                end
                else begin
                    r_checded_data[1] <=  r_checded_data[1];  
                    r_checded_data[2] <=  r_checded_data[2];  
                    r_checded_data[3] <=  r_checded_data[3];  
                    r_checded_data[4] <=  r_checded_data[4];  
                    r_checded_data[5] <=  r_checded_data[5];  
                    r_checded_data[6] <=  r_checded_data[6];  
                    r_checded_data[7] <=  r_checded_data[7];  
                    r_checded_data[8] <=  r_checded_data[8];  
                    r_checded_data[9] <=  r_checded_data[9];  
                    r_checded_data[10] <=  r_checded_data[10];
                end
            end
    endmodule

    参考手册“axi_lite_ipif_ds765”及“AXI UART Lite v2.0  pg142”

    AXI-LITE接口,完全按照手册上的时序才能实现!!

    有陀螺数据包解包校验代码,包格式说明如下图,包校验通过才更新缓存寄存器,保证缓存寄存器内存储的数据是最新的正确数据包。

    需注意,IP使用主时钟100MHz产生波特率,100M时钟并不能产生较准确的波特率,波特率较高时出现异常,后改用14.7456M晶振,5倍频后作为UART IP的输入时钟,通信正常。

  • 相关阅读:
    线性代数07.Ax=0:主变量,特解
    线性代数06.列空间和零空间
    线性代数05.转置、置换、向量空间
    线性代数04.A的LU分解
    线性代数03.矩阵的乘法和逆
    .线性代数02.矩阵消元
    KEIL中三种编译模式以及对变量空间的影响
    Python之常用模块(三)random模块和序列化
    Python之常用模块(二)time模块与datetime模块
    Python之常用模块(一)自定义模块
  • 原文地址:https://www.cnblogs.com/dlutccj/p/10261358.html
Copyright © 2011-2022 走看看