`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的输入时钟,通信正常。