|
楼主 |
发表于 2013-10-23 14:25:25
|
显示全部楼层
串口接收部分的代码如下:
//功能:串口接收模块
module rxd(
clk_i, //时钟
resetn_i, //复位
rx_data_i, //接收的串行数据
baud_tick_i, //8倍波特率信号
parity_en_i, //校验位使能
parity_type_i, //校验位类型选择
frame_bits_i, //接收帧长度
stop_bits_i, //停止位长度
read_status_i, //读取工作状态
data_o, //接收到数据
parity_err_o, //校验错误
overframe_err_o, //帧错误
rx_rdy_o //接收准备好信号
);
//输入信号
input clk_i;
input resetn_i;
input rx_data_i;
input baud_tick_i;
input parity_en_i; //1'b1:使能校验;1'b0:禁止校验
input parity_type_i; //1'b1:奇校验;1'b0:偶校验
input stop_bits_i; //1'b1:2bit停止位;1'b0:1bit停止位
input[1:0] frame_bits_i; //2'b00:5bit;2'b01:6bit;2'b10:7bit;2'b11:8bit
input read_status_i;
//输出信号
output[7:0] data_o;
output parity_err_o;
output overframe_err_o;
output rx_rdy_o;
reg[7:0] data_o;
reg parity_err_o;
reg overframe_err_o; //1'b1:帧错误,1'b0:帧正常
reg rx_rdy_o; //1'b1:数据有效可读,1'b0:正在接收数据
parameter
IDLE = 5'h0,
RX_START = 5'h1,
RX_BIT0_WAITE = 5'h2,
RX_BIT0 = 5'h3,
RX_BIT1_WAITE = 5'h4,
RX_BIT1 = 5'h5,
RX_BIT2_WAITE = 5'h6,
RX_BIT2 = 5'h7,
RX_BIT3_WAITE = 5'h8,
RX_BIT3 = 5'h9,
RX_BIT4_WAITE = 5'ha,
RX_BIT4 = 5'hb,
RX_BIT5_WAITE = 5'hc,
RX_BIT5 = 5'hd,
RX_BIT6_WAITE = 5'he,
RX_BIT6 = 5'hf,
RX_BIT7_WAITE = 5'h10,
RX_BIT7 = 5'h11,
RX_PARITY_WAITE = 5'h12,
RX_PARITY = 5'h13,
RX_STOP1_WAITE = 5'h14,
RX_STOP1 = 5'h15,
RX_STOP2_WAITE = 5'h16,
RX_STOP2 = 5'h17,
RX_OVF = 5'h18;
//定义内部信号
reg[1:0] divisor_cnt; //波特率分频
reg clr_divisor_cnt; //
reg rx_baud_tick; //2倍波特率信号
reg[4:0] rx_state;
reg[7:0] data_rxd;
reg parity_value;
reg overframe; //帧错误标志,1'b1:帧错误,1'b0:帧正常
reg rx_data_rdy; //数据有效标志,1'b1:数据有效可读,1'b0:正在接收数据
reg rx_data_rdy_d1;
reg overframe_d1;
reg parity_value_d1;
reg parity_value_d2;
/**********************************************
分频计数器
生成2倍波特率脉冲,一个时钟周期宽度
***********************************************/
always @(posedge clk_i or negedge resetn_i)
begin
if(!resetn_i)
begin
divisor_cnt <= 2'h0;
rx_baud_tick <= 1'b0;
end
else if(clr_divisor_cnt)
begin
divisor_cnt <= 2'h0;
end
else if((baud_tick_i == 1'b1) && (rx_state != IDLE))
begin
if(divisor_cnt == 2'h3)
begin
divisor_cnt <= 2'h0;
rx_baud_tick <= 1'b1;
end
else
begin
divisor_cnt <= divisor_cnt + 1'b1;
end
end
else
begin
rx_baud_tick <= 1'b0;
end
end
/*********************************************
接收状态机
**********************************************/
always @(posedge clk_i or negedge resetn_i)
begin
if(!resetn_i)
begin
rx_state <= IDLE;
clr_divisor_cnt <= 1'b0;
overframe <= 1'b0;
data_rxd <= 8'h0;
parity_value <= 1'b0;
rx_data_rdy <= 1'b0;
end
else
begin
clr_divisor_cnt <= 1'b0;
case(rx_state)
IDLE:
begin
parity_value <= 1'b0;
overframe <= 1'b0;
rx_data_rdy <= 1'b0;
if(baud_tick_i == 1'b1)
begin
if(rx_data_i == 1'b0)
begin
clr_divisor_cnt <= 1'b1;
rx_state <= RX_START;
end
else
begin
clr_divisor_cnt <= 1'b0;
rx_state <= IDLE;
end
end
else
begin
clr_divisor_cnt <= 1'b0;
rx_state <= IDLE;
end
end
RX_START:
begin
if(rx_baud_tick == 1'b1)
begin
if(rx_data_i == 1'b1)
begin
rx_state <= RX_OVF;
end
else
begin
rx_state <= RX_BIT0_WAITE;
end
end
else
begin
rx_state <= RX_START;
end
end
RX_BIT0_WAITE:
begin
if(rx_baud_tick == 1'b1)
begin
rx_state <= RX_BIT0;
end
else
begin
rx_state <= RX_BIT0_WAITE;
end
end
RX_BIT0:
begin
if(rx_baud_tick == 1'b1)
begin
data_rxd[0] <= rx_data_i;
parity_value <= parity_value ^ rx_data_i;
rx_state <= RX_BIT1_WAITE;
end
else
begin
rx_state <= RX_BIT0;
end
end
RX_BIT1_WAITE:
begin
if(rx_baud_tick == 1'b1)
begin
rx_state <= RX_BIT1;
end
else
begin
rx_state <= RX_BIT1_WAITE;
end
end
RX_BIT1:
begin
if(rx_baud_tick == 1'b1)
begin
data_rxd[1] <= rx_data_i;
parity_value <= parity_value ^ rx_data_i;
rx_state <= RX_BIT2_WAITE;
end
else
begin
rx_state <= RX_BIT1;
end
end
RX_BIT2_WAITE:
begin
if(rx_baud_tick == 1'b1)
begin
rx_state <= RX_BIT2;
end
else
begin
rx_state <= RX_BIT2_WAITE;
end
end
RX_BIT2:
begin
if(rx_baud_tick == 1'b1)
begin
data_rxd[2] <= rx_data_i;
parity_value <= parity_value ^ rx_data_i;
rx_state <= RX_BIT3_WAITE;
end
else
begin
rx_state <= RX_BIT2;
end
end
RX_BIT3_WAITE:
begin
if(rx_baud_tick == 1'b1)
begin
rx_state <= RX_BIT3;
end
else
begin
rx_state <= RX_BIT3_WAITE;
end
end
RX_BIT3:
begin
if(rx_baud_tick == 1'b1)
begin
data_rxd[3] <= rx_data_i;
parity_value <= parity_value ^ rx_data_i;
rx_state <= RX_BIT4_WAITE;
end
else
begin
rx_state <= RX_BIT3;
end
end
RX_BIT4_WAITE:
begin
if(rx_baud_tick == 1'b1)
begin
rx_state <= RX_BIT4;
end
else
begin
rx_state <= RX_BIT4_WAITE;
end
end
RX_BIT4:
begin
if(rx_baud_tick == 1'b1)
begin
data_rxd[4] <= rx_data_i;
parity_value <= parity_value ^ rx_data_i;
if((frame_bits_i == 2'b00) && (parity_en_i == 1'b0)) //5bit, 无效验位
begin
rx_state <= RX_STOP1_WAITE;
end
else if((frame_bits_i == 2'b00) && (parity_en_i == 1'b1)) //5bit,有效验位
begin
rx_state <= RX_PARITY_WAITE;
end
else
begin
rx_state <= RX_BIT5_WAITE;
end
end
else
begin
rx_state <= RX_BIT4;
end
end
RX_BIT5_WAITE:
begin
if(rx_baud_tick == 1'b1)
begin
rx_state <= RX_BIT5;
end
else
begin
rx_state <= RX_BIT5_WAITE;
end
end
RX_BIT5:
begin
if(rx_baud_tick == 1'b1)
begin
data_rxd[5] <= rx_data_i;
parity_value <= parity_value ^ rx_data_i;
if((frame_bits_i == 2'b01) && (parity_en_i == 1'b0)) //6bit, 无效验位
begin
rx_state <= RX_STOP1_WAITE;
end
else if((frame_bits_i == 2'b01) && (parity_en_i == 1'b1))//6bit,有效验位
begin
rx_state <= RX_PARITY_WAITE;
end
else
begin
rx_state <= RX_BIT6_WAITE;
end
end
else
begin
rx_state <= RX_BIT5;
end
end
RX_BIT6_WAITE:
begin
if(rx_baud_tick == 1'b1)
begin
rx_state <= RX_BIT6;
end
else
begin
rx_state <= RX_BIT6_WAITE;
end
end
RX_BIT6:
begin
if(rx_baud_tick == 1'b1)
begin
data_rxd[6] <= rx_data_i;
parity_value <= parity_value ^ rx_data_i;
if((frame_bits_i == 2'b10) && (parity_en_i == 1'b0)) //7bit, 无效验位
begin
rx_state <= RX_STOP1_WAITE;
end
else if((frame_bits_i == 2'b10) && (parity_en_i == 1'b1))//7bit,有效验位
begin
rx_state <= RX_PARITY_WAITE;
end
else
begin
rx_state <= RX_BIT7_WAITE;
end
end
else
begin
rx_state <= RX_BIT6;
end
end
RX_BIT7_WAITE:
begin
if(rx_baud_tick == 1'b1)
begin
rx_state <= RX_BIT7;
end
else
begin
rx_state <= RX_BIT7_WAITE;
end
end
RX_BIT7:
begin
if(rx_baud_tick == 1'b1)
begin
data_rxd[7] <= rx_data_i;
parity_value <= parity_value ^ rx_data_i;
rx_state <= RX_BIT7_WAITE;
if(parity_en_i == 1'b1) //8bit, 有效验位
begin
rx_state <= RX_PARITY_WAITE;
end
else //8bit, 无效验位
begin
rx_state <= RX_STOP1_WAITE;
end
end
else
begin
rx_state <= RX_BIT7;
end
end
RX_PARITY_WAITE:
begin
if(rx_baud_tick == 1'b1)
begin
rx_state <= RX_PARITY;
end
else
begin
rx_state <= RX_PARITY_WAITE;
end
end
RX_PARITY:
begin
if(rx_baud_tick == 1'b1)
begin
if(parity_type_i == 1'b1) //奇校验
begin
parity_value <= ((~parity_value) != rx_data_i);
end
else //偶校验
begin
parity_value <= (parity_value != rx_data_i);
end
rx_state <= RX_STOP1_WAITE;
end
else
begin
rx_state <= RX_PARITY;
end
end
RX_STOP1_WAITE:
begin
rx_data_rdy <= 1'b1;
if(rx_baud_tick == 1'b1)
begin
rx_state <= RX_STOP1;
end
else
begin
rx_state <= RX_STOP1_WAITE;
end
end
RX_STOP1:
begin
if(rx_baud_tick == 1'b1)
begin
if(stop_bits_i == 1'b1)
begin
rx_state <= RX_STOP2_WAITE;
end
else
begin
rx_state <= IDLE;
end
end
else
begin
rx_state <= RX_STOP1;
end
end
RX_STOP2_WAITE:
begin
if(rx_baud_tick == 1'b1)
begin
rx_state <= RX_STOP2;
end
else
begin
rx_state <= RX_STOP2_WAITE;
end
end
RX_STOP2:
begin
if(rx_baud_tick == 1'b1)
begin
rx_state <= IDLE;
end
else
begin
rx_state <= RX_STOP2;
end
end
RX_OVF:
begin
overframe <= 1'b1;
rx_state <= IDLE;
end
default:
begin
rx_state <= IDLE;
end
endcase
end
end
/****************************************************
读取工作状态后,清除帧、校验错误、空满标志位
****************************************************/
always @(posedge clk_i or negedge resetn_i)
begin
if(!resetn_i)
begin
parity_err_o <= 1'b0;
overframe_err_o <= 1'b0;
rx_rdy_o <= 1'b0;
end
else if(read_status_i)
begin
parity_err_o <= 1'b0;
overframe_err_o <= 1'b0;
rx_rdy_o <= 1'b0;
end
else
begin
parity_err_o <= parity_err_o | ((!parity_value_d2) && (parity_value_d1));
overframe_err_o <= overframe_err_o | ((!overframe_d1) && (overframe));
rx_rdy_o <= rx_rdy_o | ((!rx_data_rdy_d1) && (rx_data_rdy));
end
end
/******************************************
送出接收到的数据
*******************************************/
always @(posedge clk_i or negedge resetn_i)
begin
if(!resetn_i)
begin
data_o <= 8'h0;
end
else if(rx_data_rdy)
begin
case(frame_bits_i)
2'b00:
begin
data_o <= {3'b0,data_rxd[4:0]};
end
2'b01:
begin
data_o <= {2'b0,data_rxd[5:0]};
end
2'b10:
begin
data_o <= {1'b0,data_rxd[6:0]};
end
2'b11:
begin
data_o <= data_rxd;
end
endcase
end
end
/*****************************************
延时,用于边沿检测
******************************************/
always @(posedge clk_i or negedge resetn_i)
begin
if(!resetn_i)
begin
rx_data_rdy_d1 <= 1'b0;
overframe_d1 <= 1'b0;
end
else
begin
rx_data_rdy_d1 <= rx_data_rdy;
overframe_d1 <= overframe;
end
end
always @(posedge clk_i or negedge resetn_i)
begin
if(!resetn_i)
begin
parity_value_d1 <= 1'b0;
parity_value_d2 <= 1'b0;
end
else if(rx_state == RX_STOP1_WAITE)
begin
parity_value_d1 <= parity_value;
parity_value_d2 <= parity_value_d1;
end
else
begin
parity_value_d1 <= 1'b0;
parity_value_d2 <= 1'b0;
end
end
endmodule |
|