学习ZYNQ之FPGA13.1(串口)

学习ZYNQ之FPGA13.1(串口)_第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

学习ZYNQ之FPGA13.1(串口)_第2张图片

串口发送模块:

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.增加发送时间,可以选择十分之九或者五分之四的波特率等等。

存在问题:

思考回环设计

你可能感兴趣的:(FPGA)