串口接收模块是个参数化可配置模块,参数“CLK_FRE”定义接收模块的系统时钟频率,单位是 Mhz,参数“BAUD_RATE”是波特率。接收状态机状态转换图如下:“S_IDLE”状态为空闲状态,上电后进入“S_IDLE”,如果信号“rx_pin”有下降沿,我们认为是串口的起始位,进入状态“S_START” ,等一个 BIT 时间起始位结束后进入数据位接收状态“S_REC_BYTE” ,本实验中数据位设计是 8 位,接收完成以后进入“S_STOP”状态,在“S_STOP”没有等待一个 BIT 周期, 只等待了半个 BIT 时间,这是因为如果等待了一个周期,有可能会错过下一个数据的起始位判断,最后进入“S_DATA”状态,将接收到的数据送到其他模块。 在这个模块我们提一点:为了满足采样定理,在接受数据时每个数据都在波特率计数器的时间中点进行采样,以避免数据出错的情况:
//////////////////////////////////////////////////////////////////////////////////// // // // // Author: lhj // // // // ALINX(shanghai) Technology Co.,Ltd // // heijin // // WEB: http://www.alinx.cn/ // // BBS: http://www.heijin.org/ // // // ////////////////////////////////////////////////////////////////////////////////// // // // Copyright (c) 2017,ALINX(shanghai) Technology Co.,Ltd // // All rights reserved // // // // This source file may be used and distributed without restriction provided // // that this copyright statement is not removed from the file and that any // // derivative work contains the original copyright notice and the associated // // disclaimer. // // // ////////////////////////////////////////////////////////////////////////////////// //================================================================================ // Revision History: // Date By Revision Change Description //-------------------------------------------------------------------------------- //2018/1/3 1.0 Original //*******************************************************************************/ module uart_test( input sys_clk, input rst_n, input uart_rx, output uart_tx ); parameter CLK_FRE = 50;//Mhz localparam IDLE = 0; localparam SEND = 1; //send HELLO ALINX\r\n localparam WAIT = 2; //wait 1 second and send uart received data reg[7:0] tx_data; reg[7:0] tx_str/*synthesis syn_keep=1*/; reg tx_data_valid; wire tx_data_ready; reg[7:0] tx_cnt; wire[7:0] rx_data; wire rx_data_valid; wire rx_data_ready; reg[31:0] wait_cnt; reg[3:0] state; assign rx_data_ready = 1'b1;//always can receive data, //if HELLO ALINX\r\n is being sent, the received data is discarded always@(posedge sys_clk or negedge rst_n) begin if(rst_n == 1'b0) begin wait_cnt <= 32'd0; tx_data <= 8'd0; state <= IDLE; tx_cnt <= 8'd0; tx_data_valid <= 1'b0; end else case(state) IDLE: state <= SEND; SEND: begin wait_cnt <= 32'd0; tx_data <= tx_str; if(tx_data_valid == 1'b1 && tx_data_ready == 1'b1 && tx_cnt < 8'd12)//Send 12 bytes data begin tx_cnt <= tx_cnt + 8'd1; //Send data counter end else if(tx_data_valid && tx_data_ready)//last byte sent is complete begin tx_cnt <= 8'd0; tx_data_valid <= 1'b0; state <= WAIT; end else if(~tx_data_valid) begin tx_data_valid <= 1'b1; end end WAIT: begin wait_cnt <= wait_cnt + 32'd1; if(rx_data_valid == 1'b1) begin tx_data_valid <= 1'b1; tx_data <= rx_data; // send uart received data end else if(tx_data_valid && tx_data_ready) begin tx_data_valid <= 1'b0; end else if(wait_cnt >= CLK_FRE * 1000000) // wait for 1 second state <= SEND; end default: state <= IDLE; endcase end //combinational logic //Send "HELLO ALINX\r\n" always@(*) begin case(tx_cnt) 8'd0 : tx_str <= "H"; 8'd1 : tx_str <= "E"; 8'd2 : tx_str <= "L"; 8'd3 : tx_str <= "L"; 8'd4 : tx_str <= "O"; 8'd5 : tx_str <= " "; 8'd6 : tx_str <= "A"; 8'd7 : tx_str <= "L"; 8'd8 : tx_str <= "I"; 8'd9 : tx_str <= "N"; 8'd10: tx_str <= "X"; // 8'd11: tx_str <= "\r"; 8'd11: tx_str <= 8'h0d; 8'd12: tx_str <= "\n"; default:tx_str <= 8'd0; endcase end uart_rx# ( .CLK_FRE(CLK_FRE), .BAUD_RATE(115200) ) uart_rx_inst ( .clk (sys_clk ), .rst_n (rst_n ), .rx_data (rx_data ), .rx_data_valid (rx_data_valid ), .rx_data_ready (rx_data_ready ), .rx_pin (uart_rx ) ); uart_tx# ( .CLK_FRE(CLK_FRE), .BAUD_RATE(115200) ) uart_tx_inst ( .clk (sys_clk ), .rst_n (rst_n ), .tx_data (tx_data ), .tx_data_valid (tx_data_valid ), .tx_data_ready (tx_data_ready ), .tx_pin (uart_tx ) ); endmodule
复制代码