ZYNQ_project:uart(odd,even)

概念:

UART(Universal Asynchronous Receiver-Transmitter):即通用异步收发器,是一种通用串行数据总线,用于异步通信。一般UART接口常指串口。

UART在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换成并行数据。

单工通信:数据只能沿一个方向传输。

半双工通信:数据可以沿两个方向传输,但需要分时进行。

全双工通信:数据可以同时进行双向传输。

同步通信:带时钟端口的数据传输。

异步通信:没有时钟端口,发送方和接收方使用各自的时钟控制数据的收发过程。

常见串行通信接口:

ZYNQ_project:uart(odd,even)_第1张图片

 模块框图:

ZYNQ_project:uart(odd,even)_第2张图片

时序图:

ZYNQ_project:uart(odd,even)_第3张图片

 ZYNQ_project:uart(odd,even)_第4张图片

代码:

// uart的接收模块,要求波特率可调,回环实验
// 完成回环实验后加入校验位
// 然后加入led与蜂鸣器的控制模块
`include         "para.v"
module rx (
    input       wire                sys_clk     ,
    input       wire                sys_rst_n   ,
    input       wire                rx          ,

    output      reg     [7:0]       po_data     , // port_output
    output      reg                 po_flag     
);
    // parameter
    parameter   MAX_BPS_CNT = `CLOCK/`BPS   ,//434 ,
                MAX_BIT_CNT = `BIT_CHACK    ;//10   ; 
    localparam  RX_MOD      = 1'b1          ,
                CHECK_MOD   = `EVEN         ;
    // reg signal define
    reg                 rx_r1    ;
    reg                 rx_r2    ;
    reg     [31:0]      cnt_bps  ;
    reg                 work     ;
    reg     [3:0]       cnt_bit  ;
    reg     [7:0]       data_reg ;
    reg                 check    ;
    reg                 check_reg;
    // wire signal define
    wire                nege    ;
    /*******************************************************************/
    // // reg signal define
    // reg                 rx_r1   ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            rx_r1 <= 1'b1 ;
        else
            rx_r1 <= rx ;
    end
    // reg                 rx_r2   ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            rx_r2 <= 1'b1 ;
        else
            rx_r2 <= rx_r1 ;
    end
    // reg                 work    ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            work <= 1'b0 ;
        else if(nege)
            work <= 1'b1 ;
        else if((cnt_bit == ((MAX_BIT_CNT - 1))) && (cnt_bps == (MAX_BPS_CNT - 1))) // 这俩条件可以用end_cnt_XXX来代替,组合逻辑赋
            work <= 1'b0 ;
        else 
            work <= work ;
    end
    // reg     [31:0]      cnt_bps ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_bps <= 32'd0 ;
        else if(work && (cnt_bps == (MAX_BPS_CNT - 1)))
            cnt_bps <= 32'd0 ;
        else if(work)
            cnt_bps <= cnt_bps + 1'b1 ;
        else 
            cnt_bps <= 32'd0 ;
    end
    // reg     [3:0]       cnt_bit ; 应该会归0
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_bit <= 4'd0 ;
        else if (work && (cnt_bps == (MAX_BPS_CNT - 1) && cnt_bit == (MAX_BIT_CNT - 1)))
            cnt_bit <= 4'd0 ;
        else if (work && (cnt_bps == (MAX_BPS_CNT - 1)))
            cnt_bit <= cnt_bit + 1'b1 ;
        else if(work)
            cnt_bit <= cnt_bit ;
        else 
            cnt_bit <= 8'd0 ;
    end
    // reg     [7:0]       data_reg;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            data_reg <= 8'd0 ;
        else if(work && cnt_bps == (MAX_BPS_CNT/2)) begin // 采样,采集数据的时刻
            case (cnt_bit)
                0 : data_reg <= 8'd0 ;
                1 : data_reg[cnt_bit - 1] <= rx_r2 ;
                2 : data_reg[cnt_bit - 1] <= rx_r2 ;
                3 : data_reg[cnt_bit - 1] <= rx_r2 ;
                4 : data_reg[cnt_bit - 1] <= rx_r2 ;
                5 : data_reg[cnt_bit - 1] <= rx_r2 ;
                6 : data_reg[cnt_bit - 1] <= rx_r2 ;
                7 : data_reg[cnt_bit - 1] <= rx_r2 ;
                8 : data_reg[cnt_bit - 1] <= rx_r2 ;
                default: data_reg <= data_reg ;
            endcase
        end else
            data_reg <= data_reg ;
    end
    // // wire signal define
    // wire                nege    ;
    assign  nege = ~rx_r1 && rx_r2 ;
    // reg                 check    ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            check <= 1'b0 ;
        else if(CHECK_MOD && (cnt_bit == ((MAX_BIT_CNT - 2))) && (cnt_bps == (MAX_BPS_CNT - 1)))
            check <= ~^data_reg ;
        else if(~CHECK_MOD && (cnt_bit == ((MAX_BIT_CNT - 2))) && (cnt_bps == (MAX_BPS_CNT - 1)))
            check <= ^data_reg ;    
        else 
            check <= check ;
    end  
    // reg                 check_reg;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            check_reg <= 1'b0 ;
        else if((cnt_bit == ((MAX_BIT_CNT - 1))) && (cnt_bps == (MAX_BPS_CNT /2)))
            check_reg <= rx_r2 ;
        else 
            check_reg <= check_reg ;
    end  
    // output      reg     [7:0]       po_data     , // port_output
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            po_data <= 8'd0 ;
        else if((check == check_reg) && (cnt_bit == ((MAX_BIT_CNT - 1))) && (cnt_bps == (MAX_BPS_CNT - 1)))
            po_data <= data_reg ;
        else if(RX_MOD)
            po_data <= po_data ;
        else 
            po_data <= 8'd0 ;
    end
    // output      reg                 po_flag   
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            po_flag <= 8'd0 ;
        else if((check == check_reg) && ((cnt_bit == ((MAX_BIT_CNT - 1))) && (cnt_bps == (MAX_BPS_CNT - 1)))) 
            po_flag <= 1'b1 ;
        else 
            po_flag <= 8'd0 ;
    end  

endmodule
// uart的数据发送模块。停止位 1bit
`include         "para.v"
module  tx(
    input       wire                sys_clk     ,
    input       wire                sys_rst_n   ,
    input       wire    [7:0]       pi_data     ,
    input       wire                pi_flag     ,

    output      reg                 tx         
);
    // parameter
    parameter   MAX_BPS_CNT = `CLOCK/`BPS   ,
                MAX_BIT_CNT = `BIT_CHACK + 1;
    localparam  CHECK_MOD   = `EVEN         ;
    // reg signal define
    reg     [7:0]       data_reg ;
    reg                 work     ;
    reg     [31:0]      cnt_bps  ; 
    reg     [3:0]       cnt_bit  ; 

    /********************************************************************/
    // // reg signal define
    // reg     [7:0]       data_reg ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            data_reg <= 8'd0 ;
        else if(pi_flag)
            data_reg <= pi_data ;
        else 
            data_reg <= data_reg ;
    end
    // reg                 work     ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            work <= 1'b0 ;
        else if(pi_flag)
            work <= 1'b1 ;
        else if(cnt_bps == (MAX_BPS_CNT - 1) && cnt_bit == (MAX_BIT_CNT - 1))
            work <= 1'b0 ;
        else 
            work <= work ;
    end
    // reg     [31:0]      cnt_bps  ; 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_bps <= 32'd0 ;
        else if((work && (cnt_bps == (MAX_BPS_CNT - 1))) 
            || (work && (cnt_bit == (MAX_BIT_CNT - 1)) && cnt_bps == (MAX_BPS_CNT - 1)))
            cnt_bps <= 32'd0 ;
        else if(work)
            cnt_bps <= cnt_bps + 1'b1 ;
        else 
            cnt_bps <= 32'd0 ;
    end
    // reg     [3:0]       cnt_bit  ; 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_bit <= 4'd0 ;
        else if(work && (cnt_bps == (MAX_BPS_CNT - 1)) && cnt_bit == (MAX_BIT_CNT - 1))
            cnt_bit <= 4'd0 ;
        else if(work && (cnt_bps == (MAX_BPS_CNT - 1)))
            cnt_bit <= cnt_bit + 1'b1 ;
        else if(work)
            cnt_bit <= cnt_bit ;
        else 
            cnt_bit <= 4'd0 ;
    end
    // output      reg                 tx          
    always @(*) begin
        if(~sys_rst_n)
            tx = 1'b1 ;
        else if(work) begin
            case (cnt_bit)
            4'd0:   tx = 1'b0 ; 
            4'd1:   tx = data_reg[cnt_bit - 1] ; 
            4'd2:   tx = data_reg[cnt_bit - 1] ; 
            4'd3:   tx = data_reg[cnt_bit - 1] ; 
            4'd4:   tx = data_reg[cnt_bit - 1] ; 
            4'd5:   tx = data_reg[cnt_bit - 1] ; 
            4'd6:   tx = data_reg[cnt_bit - 1] ; 
            4'd7:   tx = data_reg[cnt_bit - 1] ; 
            4'd8:   tx = data_reg[cnt_bit - 1] ; 
            4'd9:   begin 
                    if(CHECK_MOD)
                        tx = ~^data_reg ;
                    else 
                        tx = ^data_reg ;
                    end
            default: tx = 1'b1 ;
            endcase
        end else 
            tx = 1'b1 ;
    end
endmodule

 

module  top(
    input       wire                sys_clk     ,
    input       wire                sys_rst_n   ,
    input       wire                rx          ,

    output      wire                tx          
);
    // 例化间连线 Wiring between instantiations
    wire                clk_100Mhz  ;
    wire                clk_50Mhz   ;
    wire                locked      ; 
    wire                rst_n       ; 
    assign              rst_n   = sys_rst_n && locked ;
    wire    [7:0]       po_data     ;
    wire                po_flag     ;
pll pll_inst(
  .clk_in1          ( sys_clk       ) ,
  .resetn           ( sys_rst_n     ) ,

  .clk_out1         ( clk_100Mhz    ) ,
  .clk_out2         ( clk_50Mhz     ) ,
  .locked           ( locked        ) 
 );

rx rx_inst(
    .sys_clk        ( clk_50Mhz     ) ,
    .sys_rst_n      ( rst_n         ) ,
    .rx             ( rx            ) ,

    .po_data        ( po_data       ) ,
    .po_flag        ( po_flag       )  
);

tx tx_inst(
    .sys_clk        ( clk_50Mhz     ) ,
    .sys_rst_n      ( rst_n         ) ,
    .pi_data        ( po_data       ) ,
    .pi_flag        ( po_flag       ) ,

    .tx             ( tx            )
);
endmodule

 

仿真:

ZYNQ_project:uart(odd,even)_第5张图片

你可能感兴趣的:(正点原子领航者7020,fpga开发)