/**
******************************************************************************
* @file rx_rs232_v6.v
* @author 西殿源
* @version V6
* @date 07/20/2012
* @brief RS232串口接收模块
* @info 1. 合并检测模块
2. 规范端口名,变量名,代码风格
3. 稳定
******************************************************************************
*/
module rx_rs232_v6(
output reg[7:0] dat_ro, //串行接收,并行输出
output reg ***_ro, //接收成功标志,脉宽一个clk周期
// output reg bit_reg_in1,
// output reg bit_reg_in2,
// output reg bit_reg_in3,
// output reg bit_reg_in4,
// output reg chk_en,
// output reg samp_en,
// output star_chk,
// output flag_start,
// output clk_w,
// output reg [8:0] baud_cnt,
// output reg [3:0] sample_cnt,
// output reg [3:0] bit_cnt,
input clk, //输入时钟,1MZ
input rst_n, //低电平复位
input rx_in //串行数据输入
);
parameter START = 4'd0;
parameter DAT0 = 4'd1;
parameter DAT1 = 4'd2;
parameter DAT2 = 4'd3;
parameter DAT3 = 4'd4;
parameter DAT4 = 4'd5;
parameter DAT5 = 4'd6;
parameter DAT6 = 4'd7;
parameter DAT7 = 4'd8;
parameter VRFY = 4'd9;
parameter STOP = 4'd10;
parameter FLAG = 4'd11;
parameter IDLE = 4'd12;
parameter YES = 1'b1;
parameter NO = 1'b0;
parameter BAUD = 9600;
parameter XTAL = 1000000;
//////////flag/////////
reg bit_reg_in1;//输入缓冲级
reg bit_reg_in2;//输入缓冲级
reg bit_reg_in3;//输入缓冲级
reg bit_reg_in4;//输入缓冲级
reg chk_en;
reg samp_en;
wire star_chk;
wire flag_start;
wire clk_w;
reg [8:0] baud_cnt; //
reg [3:0] sample_cnt; //
reg [3:0] bit_cnt;
//
reg [1:0] weig_cnt;
reg [9:0] data_temp;
/////////////////波特率相关//////////////
reg verify_reg;
parameter baud_para = 5;//324 325
reg baud_adj;
//每比特采16个点
always @(posedge clk,negedge rst_n) begin
if(!rst_n) begin
baud_adj<=0;
baud_cnt<=0;
end
else if(baud_cnt==baud_para+baud_adj) begin
baud_adj<=~baud_adj;
baud_cnt<=0;
end
else begin
baud_cnt<=baud_cnt+9'b1;
end
end
//串口协议,启动位检测
//检测启动位 1100
assign star_chk=((~bit_reg_in1)&(~bit_reg_in2)&bit_reg_in3&bit_reg_in4)? YES:NO;
//使能位采样,仅在当前位总线空闲且检测到启动位时使能,脉宽一个clk周期
assign flag_start=((chk_en==YES)&&(star_chk==YES)&&(baud_cnt==1))? YES:NO;
//忽略启动? //下降沿检测,仅
//维持一个clk周期
//采样时钟,脉宽一个clk周期,脉间距6-7个clk周期
assign clk_w = ( (baud_cnt==2) && (samp_en==YES) );
always @(posedge clk,negedge rst_n) begin
if(!rst_n) begin
chk_en <= YES; //使能启动位检测
samp_en <= NO; //除能信号采样
end
else if(flag_start) begin
chk_en <= NO; //忽略启动位检测
samp_en <= YES; //使能信号采样
end
else if(***_ro == YES) begin
chk_en <= YES;
samp_en <= NO;
end
else if(baud_cnt == 0) begin
bit_reg_in1<=rx_in;
bit_reg_in2<=bit_reg_in1;
bit_reg_in3<=bit_reg_in2;
bit_reg_in4<=bit_reg_in3;
end
else ;
end
always @(posedge clk,negedge rst_n) begin
if(!rst_n) begin
data_temp <= 10'd0;
***_ro <= NO;
dat_ro <= 8'd0;
end
else if(flag_start) begin
sample_cnt <= 4'd1;
bit_cnt <= 4'd0;
end
else if(clk_w) begin
sample_cnt <= sample_cnt + 4'd1;
if(sample_cnt == 4'd15) begin
if(bit_cnt == 4'd9) begin
***_ro <= YES;
dat_ro <= data_temp[8:1];
end
else bit_cnt <= bit_cnt + 4'd1;
end
else ;
case(sample_cnt)
7 : weig_cnt <= rx_in;
8 : weig_cnt <= weig_cnt + rx_in;
9 : weig_cnt <= weig_cnt + rx_in;
14 : begin
if(weig_cnt > 1) data_temp[bit_cnt] <= 1'b1;
else data_temp[bit_cnt] <= 1'b0;
end
default : ;
endcase
end
else ***_ro <= NO;
end
endmodule
文章评论(0条评论)
登录后参与讨论