module rx(clk, rx, dataout, rdsig, dataerror, frameerror,receive);
input clk; //采样时钟
input rx; //UART数据输入
output dataout; //接收数据输出
output rdsig; //接收数据有效,高说明接收到一个字节
output dataerror; //数据出错指示
output frameerror; //帧出错指示
output receive;
reg[7:0] dataout;
reg rdsig, dataerror;
reg frameerror;
reg [7:0] cnt;
reg rxbuf, rxfall, receive;
parameter paritymode = 1'b0;
reg presult, idle;
always @(posedge clk) //检测线路rx的下降沿, 线路空闲的时候rx为高电平
begin
rxbuf <= rx;
rxfall <= rxbuf & (~rx);
end
always @(posedge clk)
begin
if (rxfall && (~idle)) //检测到线路的下降沿并且原先线路为空闲,启动接收数据进程
begin
receive <= 1'b1; //开始接收数据
end
else if(cnt == 8'd169) //接收数据完成
begin
receive <= 1'b0;
end
end
/////////////////////////////////////////////////////////////////////////
//使用176个时钟接收一个数据(起始位、8位数据、奇偶校验位、停止位),每位占用16个时钟//
////////////////////////////////////////////////////////////////////////
always @(posedge clk)
begin
if(receive == 1'b1)
begin
case (cnt)
8'd7: //0~15个时钟为接收第一个比特,起始位
begin
idle <= 1'b1;
cnt <= cnt + 8'd1;
rdsig <= 1'b0;
end
8'd24: //16~31个时钟为第1个bit数据,取中间第24个时钟的采样值
begin
idle <= 1'b1;
dataout[0] <= rx;
presult <= paritymode^rx;
cnt <= cnt + 8'd1;
rdsig <= 1'b0;
end
8'd40: //47~32个时钟为第2个bit数据,取中间第40个时钟的采样值
begin
idle <= 1'b1;
dataout[1] <= rx;
presult <= presult^rx;
cnt <= cnt + 8'd1;
rdsig <= 1'b0;
end
8'd56: //63~48个时钟为第3个bit数据,取中间第56个时钟的采样值
begin
idle <= 1'b1;
dataout[2] <= rx;
presult <= presult^rx;
cnt <= cnt + 8'd1;
rdsig <= 1'b0;
end
8'd72: //79~64个时钟为第4个bit数据,取中间第72个时钟的采样值
begin
idle <= 1'b1;
dataout[3] <= rx;
presult <= presult^rx;
cnt <= cnt + 8'd1;
rdsig <= 1'b0;
end
8'd88: //95~80个时钟为第5个bit数据,取中间第88个时钟的采样值
begin
idle <= 1'b1;
dataout[4] <= rx;
presult <= presult^rx;
cnt <= cnt + 8'd1;
rdsig <= 1'b0;
end
8'd104: //111~96个时钟为第6个bit数据,取中间第104个时钟的采样值
begin
idle <= 1'b1;
dataout[5] <= rx;
presult <= presult^rx;
cnt <= cnt + 8'd1;
rdsig <= 1'b0;
end
8'd120: //127~112个时钟为第7个bit数据,取中间第120个时钟的采样值
begin
idle <= 1'b1;
dataout[6] <= rx;
presult <= presult^rx;
cnt <= cnt + 8'd1;
rdsig <= 1'b0;
end
8'd136: //143~128个时钟为第8个bit数据,取中间第136个时钟的采样值
begin
idle <= 1'b1;
dataout[7] <= rx;
presult <= presult^rx;
cnt <= cnt + 8'd1;
rdsig <= 1'b0; //接收数据有效
end
8'd152: //159~144个时钟为接收奇偶校验位,取中间第152个时钟的采样值
begin
idle <= 1'b1;
if(presult == rx)
dataerror <= 1'b0;
else
dataerror <= 1'b1; //如果奇偶校验位不对,表示数据出错
cnt <= cnt + 8'd1;
rdsig <= 1'b0;
end
8'd168: //160~175个时钟为接收停止位,取中间第168个时钟的采样值
begin
idle <= 1'b1;
if(1'b1 == rx)
frameerror <= 1'b0;
else
frameerror <= 1'b1; //如果没有接收到停止位,表示帧出错
cnt <= cnt + 8'd1;
rdsig <= 1'b1;
end
default:
begin
cnt <= cnt + 8'd1;
end
endcase
end
else //(receive不等于1了,全部复位)
begin
cnt <= 8'd0;
idle <= 1'b0;
rdsig <= 1'b0;
end
end
endmodule |