|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
x
//////////////////////////////////////////////////////////////////////////////////
// Module Name : UART_RXD_v1_4.v
// Project Name :
// Target Devices:
// Tool Versions :
// Description :
// Dependencies :
// Revision 1.4
// Additional Comments:
//////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
module UART_RXD_v1_4(
input clk //输入时钟
,input rst_n //复位信号
,input rx_clk //接收波特率时钟
,input rxd //RXD接收信号
,output reg rx_done //接收完成
,output reg rx_en //UART接收时钟使能
,output reg [7:0] rx_data //接收数据
);
//*********************************************************************
//同步锁存,去除数据线上的干扰
//*********************************************************************
reg r_rxd; //RXD锁存
always@(posedge clk ) begin
if(!rst_n)
r_rxd <= 1'b1;
else r_rxd <= rxd ;
end
//*********************************************************************
//数据接收状态机
//*********************************************************************
localparam RX_IDLE = 3'd0; //空闲
localparam RX_START = 3'd1; //起始位
localparam RX_DAT = 3'd2; //数据位
localparam RX_STOP = 3'd3; //停止位
localparam RX_END = 3'd4; //结束
reg [3:0] cnt8; //数据计数器
reg [4:0] cnt16; //时钟计数器
reg [2:0] state; //状态机
reg [7:0] r_data; //接收数据缓存
//状态转移条件判断
always@(posedge clk) begin
if(!rst_n) begin
rx_en <= 1'b0;
state <= RX_IDLE;
end
else
case(state)
RX_IDLE : begin
if(!r_rxd)
state <= RX_START;
else
state <= state;
end
RX_START : begin
rx_en <= 1'b1;
if(cnt16<8 && r_rxd) //起始位检测8次,只要有输入为高,立即跳到RX_IDLE状态
state <= RX_IDLE;
else if(cnt16==15)
state <= RX_DAT;
else
state <= state;
end
RX_DAT : begin
if(cnt8==8&&cnt16==15) //采完8个bits后停止
state <= RX_STOP;
else
state <= state;
end
RX_STOP: begin
if(cnt16==8) //停止位检测8次表示停止位已收到,准备下一位
state <= RX_END;
else
state <= state;
end
RX_END : begin
rx_en <= 1'b0;
state <= RX_IDLE;
end
default :
state <= RX_IDLE;
endcase
end
//输出
always@(posedge clk)begin
if(!rst_n) begin
cnt8 <= 4'd0;
cnt16 <= 5'd0;
rx_done <= 1'b0;
rx_data <= 8'd0;
r_data <= 8'd0;
end
else begin
case(state)
RX_IDLE: begin
cnt8 <= 4'd0;
cnt16 <= 5'd0;
rx_done <= 1'b0;
end
RX_START: begin
if(cnt16==15)
cnt16 <= 5'd0;
else if(rx_clk)
cnt16 <= cnt16 + 1'b1;
end
RX_DAT: begin
if(cnt16==15)
cnt16 <= 5'd0;
else if(rx_clk && cnt16==7) begin
cnt8 <= cnt8 + 1'b1;
cnt16 <= cnt16 + 1'b1;
r_data[cnt8] <= r_rxd;
end
else if(rx_clk)
cnt16 <= cnt16 + 1'b1;
end
RX_STOP: begin
cnt8 <= 4'd0;
if(cnt16==15)
cnt16 <= 5'd0;
else if(rx_clk)
cnt16 <= cnt16 + 1'b1;
end
RX_END: begin
cnt8 <= 4'd0;
cnt16 <= 5'd0;
rx_done <= 1'b1;
rx_data <= r_data;
end
endcase
end
end
endmodule
|
|