http://www.cnblogs.com/BitArt/archive/2012/12/05/2802763.html
`timescale 1 ns / 1 ns
module rcvr (dout,data_ready,framing_error,parity_error,rxd,clk16x,rst,rdn) ;
input rxd ; /*数据接收端*/
input clk16x ; /*采样时钟*/
input rst ; /*复位信号,高电平有效*/
input rdn ; /*数据接收使能,低电平有效*/
output [7:0] dout ; /*数据输出*/
output data_ready ; /*数据接收完毕标志位*/
output framing_error ; /*帧错误标志位*/
output parity_error ; /*校验位错误标志位*/
reg rxd1 ;
reg rxd2 ;
reg clk1x_enable ;
reg [3:0] clkdiv ;
reg [7:0] rsr ;
reg [7:0] rbr ;
reg [3:0] no_bits_rcvd ;
reg data_ready ;
reg parity ;
reg parity_error ;
reg framing_error ;
wire clk1x ;
assign dout = !rdn ? rbr : 8'bz ; /*在允许接收的情况下,输出接收到的数据,否则保持高阻态*/
/*下降沿捕获模块*/
always @(posedge clk16x or posedge rst)
begin
if (rst)
begin
rxd1 <= 1'b1 ;
rxd2 <= 1'b1 ;
end
else
begin
rxd1 <= rxd ;
rxd2 <= rxd1 ;
end
end
always @(posedge clk16x or posedge rst)
begin
if (rst)
clk1x_enable <= 1'b0;
else if (!rxd1 && rxd2) /*如果捕获到下降沿,则开始计数*/
clk1x_enable <= 1'b1 ;
else if (no_bits_rcvd == 4'b1100)
clk1x_enable <= 1'b0 ;
end
/*数据准备好标志位的控制模块*/
always @(posedge clk16x or posedge rst or negedge rdn)
begin
if (rst)
data_ready = 1'b0 ;
else if (!rdn)
data_ready = 1'b0 ;
else
if (no_bits_rcvd == 4'b1011)
data_ready = 1'b1 ;
end
/*计数模块,产生一个对clk16x进行16分频的时钟信号,用该信号的上升沿进行采样 */
always @(posedge clk16x or posedge rst)
begin
if (rst)
clkdiv = 4'b0000 ;
else if (clk1x_enable)
clkdiv = clkdiv +1 ;
end
assign clk1x = clkdiv[3] ;
/*对clk1x进行计数*/
always @(posedge clk1x or posedge rst or negedge clk1x_enable)
if (rst)
no_bits_rcvd = 4'b0000;
else
if (!clk1x_enable)
no_bits_rcvd = 4'b0000 ;
else
no_bits_rcvd = no_bits_rcvd + 1 ;
/*采样进程*/
always @(posedge clk1x or posedge rst)
if (rst)
begin
rsr <= 8'b0 ;
rbr <= 8'b0 ;
parity <= 1'b1 ;
parity_error = 1'b0 ;
end
else
begin
if (no_bits_rcvd >= 4'b0001 && no_bits_rcvd <= 4'b1001)
begin
rsr[0] <= rxd2 ;
rsr[7:1] <= rsr[6:0] ; //数据左移
parity <= parity ^ rsr[7] ; //校验位
end
else if (no_bits_rcvd == 4'b1010)
begin
rbr <= rsr ; //输出接收到的数据
end
else if (!parity)
parity_error = 1'b1 ; //判断校验位是否正确
else if ((no_bits_rcvd == 4'b1011) && (rxd2 != 1'b1))//判断是否收到停止位,否则给出帧错误信号
framing_error = 1'b1 ;
else framing_error = 1'b0 ;
end
endmodule