欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

verilog 编写uart串口代码之接收端(RX)

程序员文章站 2022-07-09 12:47:04
...

UART模块可以划分为三个模块:接收端、发送端、以及波特率发生器。

首先我们来介绍接收端的实现:

UART整体模块框图包括了RX端和TX端;RX端有 input UART_RXD,output uart_rx_en,output uart_rx_dat[7:0];TX端有 output UART_TXD,input uart_tx_en,input uart_tx_dat[7:0]这几根信号线。数据整体流向是从左边tx_dat串行输入然后输入并行TXD;然后再到并行RXD转串行rx_dat。
verilog 编写uart串口代码之接收端(RX)
下面是UART RX的串口代码:

module UART_RX(
input              sys_clk,//clock
input              rst_n,//reset
input              baud_9600_x16_flag,
output reg         uart_rx_en,
output reg  [7:0]  uart_rx_dat,
input              UART_RXD

);

parameter    STATE_IDLE = 4'd0;
parameter    STATE_STR  = 4'd1;
parameter    STATE_D0   = 4'd2;
parameter    STATE_D1   = 4'd3;
parameter    STATE_D2   = 4'd4;
parameter    STATE_D3   = 4'd5;
parameter    STATE_D4   = 4'd6;
parameter    STATE_D5   = 4'd7;
parameter    STATE_D6   = 4'd8;
parameter    STATE_D7   = 4'd9;
parameter    STATE_STP  = 4'd10;

reg      [3:0] crt_state;
reg      [7:0] dat_tmp;
reg      [3:0] count;
reg            uart_reg1;
reg            uart_reg2;



always @ (posedge sys_clk `ES_ASYNC_RESET ) begin
    if (!rst_n) begin 
        uart_reg1   <= 1'd0;
        uart_reg2   <= 1'd1;
    end
    else begin
        uart_reg1   <= UART_RXD;    //reg beat 
        uart_reg2   <= uart_reg1;   //reg beat
    end
end

always @ (posedge sys_clk `ES_ASYNC_RESET ) begin
    if (!rst_n) begin
        crt_state   <= STATE_IDLE;
        dat_tmp     <= 8'b0;
        count       <= 4'd0;
        uart_rx_en  <= 1'd0;
        uart_rx_dat <= 8'b0;
    end
    else begin
        case(crt_state)
            STATE_IDLE : begin
                uart_rx_en      <= 1'd0;
                if((baud_9600_x16_flag) && (uart_reg2 == 1'd0)) begin  //uart start flag = 0
                    crt_state   <= STATE_STR;                          //jump state
                    dat_tmp     <= 8'b0;
                    count       <= 4'd0;
                end
            end

            STATE_STR  : begin
                if(baud_9600_x16_flag) begin
                     if(count == 4'd15) begin
                        crt_state       <= STATE_D0;                   //jump state, once into  STATE_STR the RXD must = 0 
                        count           <= 4'd0;
                     end
                     else begin
                         count <= count + 4'd1;
                     end
                end
            end

            STATE_D0   : begin
                if(baud_9600_x16_flag) begin
                     if(count == 4'd15) begin
                        count           <= 4'd0;
                        crt_state       <= STATE_D1;
                     end
                     else begin
                         count <= count + 4'd1;
                         
                         if(count == 4'd8) begin 
                            dat_tmp [0] <= uart_reg2;                  //receive data[0] ,count = 8 is in the mid to be safe
                         end
                     end
                end
            end

            STATE_D1   : begin
                if(baud_9600_x16_flag) begin
                     if(count == 4'd15) begin
                        count           <= 4'd0;
                        crt_state       <= STATE_D2;
                     end
                     else begin 
                            count <= count +4'd1;
                         if(count == 4'd8) begin 
                            dat_tmp [1] <= uart_reg2;                  //receive data[1]
                         end
                     end
                end
            end

            STATE_D2   : begin
                if(baud_9600_x16_flag) begin
                     if(count == 4'd15) begin
                        count           <= 4'd0;
                        crt_state       <= STATE_D3;
                     end
                     else begin 
                            count <= count +4'd1;
                         if(count == 4'd8) begin
                            dat_tmp [2] <= uart_reg2;                  //receive data[2]
                         end
                     end
                end
            end

            STATE_D3   : begin
               if(baud_9600_x16_flag) begin
                     if(count == 4'd15) begin
                        count           <= 4'd0;
                        crt_state       <= STATE_D4;
                     end
                     else begin 
                            count <= count +4'd1;
                         if(count == 4'd8) begin 
                            dat_tmp [3] <= uart_reg2;                  //receive data[3]
                         end
                     end
                end 
            end

            STATE_D4   : begin
                 if(baud_9600_x16_flag) begin
                     if(count == 4'd15) begin
                        count           <= 5'd0;
                        crt_state       <= STATE_D5;
                     end
                     else begin 
                            count <= count +4'd1;
                         if(count == 4'd8) begin 
                            dat_tmp [4] <= uart_reg2;                  //receive data[4]
                         end
                     end
                end
            end

            STATE_D5   : begin
                if(baud_9600_x16_flag) begin
                     if(count == 4'd15) begin
                        count           <= 4'd0;
                        crt_state       <= STATE_D6;
                     end
                     else begin 
                            count <= count +4'd1;
                         if(count == 4'd8) begin 
                            dat_tmp [5] <= uart_reg2;                  //receive data[5]
                         end
                     end
                end
            end

            STATE_D6   : begin
                if(baud_9600_x16_flag) begin
                     if(count == 4'd15) begin
                        count           <= 4'd0;
                        crt_state       <= STATE_D7;
                     end
                     else begin 
                            count <= count +4'd1;
                         if(count == 4'd8) begin 
                            dat_tmp [6] <= uart_reg2;                  //receive data[6]
                         end
                     end
                end
            end

            STATE_D7   : begin
                if(baud_9600_x16_flag) begin
                     if(count == 4'd15) begin
                        count           <= 4'd0;
                        crt_state       <= STATE_STP;
                     end
                     else begin 
                            count <= count +4'd1;
                         if(count == 4'd8) begin 
                            dat_tmp [7] <= uart_reg2;                  //receive data[7],8 bit data is already received
                         end
                     end
                end
            end

            STATE_STP  : begin
                if(baud_9600_x16_flag) begin
                     if(count == 4'd15) begin
                        count       <= 4'd0;
                        crt_state   <= STATE_IDLE;                     
                     end
                     else begin 
                            count <= count +4'd1;
                         if((count == 4'd8) && (uart_reg2 == 1'd1)) begin  //data stop flag 
                            uart_rx_dat <= dat_tmp;                        //save data
                            uart_rx_en  <= 1'd1;                           //it means data is vaild
                         end
                         else begin
                             if(count == 4'd8 && (uart_reg2 == 1'd0)) begin
                                uart_rx_en <= 1'd0;                        //data is invaild
                             end
                         end
                     end
                end
            end

            default : begin
                crt_state <= STATE_IDLE;                                   //default
            end
        endcase
    end
end
endmodule

相关标签: verilog