學習ZYNQ之FPGA13.1(串口)

   輸入信號爲時鐘信號和復位信號,輸出信號爲uart_data和uart_done,並且定義寄存器類型 

串口接收模塊:

module(
    input             sys_clk,
    input             sys_rst_n,

    input             uart_rxd,
    output reg [7:0]  uart_data,
    output reg        uart_done
)
parameter CLK_FREQ = 50_000_000;
parameter UARS_BPS = 115200;
parameter BPS_CNT = CLK_FREQ/UARS_BPS;

reg uart_rxd_d0;
reg uart_rxd_d1;
reg [15:0] clk_cnt;
reg [3:0] rx_cnt;
reg [7:0] rx_data;
reg rx_flag;

wire start_flag;
assign start_flag = uart_rxd_d1 & (~uart_rxd_d0);
//異步時鐘同步
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        uart_rxd_d0 <= 1'b1;
        uart_rxd_d1 <= 1'b1;
    end
    else begin
        uart_rxd_d0 <= uart_rxd;
        uart_rxd_d1 <= uart_rxd_d0;
    end
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        rx_flag <= 1'b0;
    else if (start_flag)
            rx_flag <= 1'b1;
         else if(rx_cnt == 4'd9 && clk_cnt == BPS_CNT/2 - 1'b1 )   
                rx_flag <= 1'b0;
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        clk_cnt <= 16'd0;
    else
        if(rx_flag) begin
            if(clk_cnt < BPS_CNT - 1'b1)
                clk_cnt <= clk_cnt + 1'b1;
            else
                clk_cnt <= 16'd0;
        end    
        else
            clk_cnt <= 16'd0;
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        rx_cnt <= 4'd0;
    else if(rx_flag) begin
            if(clk_cnt == BPS_CNT - 1'b1)
                rx_cnt <= rx_cnt + 1'b1;

end
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        rx_data <= 8'd0;
    else if(rx_flag && clk_cnt == BPS_CNT/2) begin
        case(rx_cnt)
            	4'd1 : rx_data[0] <= uart_rxd_d1;
				4'd2 : rx_data[1] <= uart_rxd_d1;
				4'd3 : rx_data[2] <= uart_rxd_d1;
				4'd4 : rx_data[3] <= uart_rxd_d1;
				4'd5 : rx_data[4] <= uart_rxd_d1;
				4'd6 : rx_data[5] <= uart_rxd_d1;
				4'd7 : rx_data[6] <= uart_rxd_d1;
				4'd8 : rx_data[7] <= uart_rxd_d1;
        endcase
    end
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
		uart_data <= 8'd0;
		uart_done <= 1'b0;
	end
	else if(rx_cnt == 4'd9) begin
			uart_data <= rx_data;
			uart_done <= 1'b1;
		 end
		 else begin 
		 	uart_data <= 8'd0;
			uart_done <= 1'b0;
		 end	
end
endmodule

串口發送模塊:

module(
    input             sys_clk,
    input             sys_rst_n,

    input             uart_en,
    output reg [7:0]  uart_din,
    output            uart_txd
)
parameter CLK_FREQ = 50_000_000;
parameter UARS_BPS = 115200;
parameter BPS_CNT = CLK_FREQ/UARS_BPS;

reg uart_en_d0;
reg uart_en_d1;
reg [15:0] clk_cnt;
reg [3:0] tx_cnt;
reg [7:0] tx_data;
reg tx_flag;

wire en_flag;
assign en_flag = uart_en_d0 & (~uart_en_d1);
//異步時鐘同步
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        uart_en_d0 <= 1'b0;
        uart_en_d1 <= 1'b0;
    end
    else begin
        uart_en_d0 <= uart_en;
        uart_en_d1 <= uart_en_d0;
    end
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        tx_data <= 8'b0;
    else if(en_flag)
            tx_data <= uart_din;
         else
            tx_data <= tx_data;

end
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        tx_flag <= 1'b0;
    else if (en_flag)
           tx_flag <= 1'b1;
         else if(tx_cnt == 4'd9 && clk_cnt == BPS_CNT/2 - 1'b1 )   
                tx_flag <= 1'b0;
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        clk_cnt <= 16'd0;
    else
        if(tx_flag) begin
            if(clk_cnt < BPS_CNT - 1'b1)
                clk_cnt <= clk_cnt + 1'b1;
            else
                clk_cnt <= 16'd0;
        end    
        else
            clk_cnt <= 16'd0;
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        tx_cnt <= 4'd0;
    else if(tx_flag) begin
            if(clk_cnt == BPS_CNT - 1'b1)
                tx_cnt <= tx_cnt + 1'b1;

end
always @ (posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        uart_txd <= 1'b0;
    else if(rx_flag && clk_cnt == 16'd0) begin
        case(tx_cnt)
            	4'd0 : uart_txd <= 1'b0;
                4'd1 : uart_txd <= tx_data[0];
				4'd2 : uart_txd <= tx_data[1];
				4'd3 : uart_txd <= tx_data[2];
				4'd4 : uart_txd <= tx_data[3];
				4'd5 : uart_txd <= tx_data[4];
				4'd6 : uart_txd <= tx_data[5];
				4'd7 : uart_txd <= tx_data[6];
				4'd8 : uart_txd <= tx_data[7];
                4'd9 : uart_txd <= 1'b1;
        endcase
    end
end
endmodule

該程序在接收發送過程中,接收到的信息會缺失,原因爲接受過程還沒結束,另一個發送過程就開始了,解決辦法有兩個:

1.增加一個迴環。

2.增加發送時間,可以選擇十分之九或者五分之四的波特率等等。

存在問題:

思考迴環設計

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章