串口数据原理图:
`timescale 1ns/10ps
module uart_rxer(
clk,
res,
RX,//用于读取数据
data_out,//输出data,将读取到的数据返回
en_data_out//使能
);
input clk,res,RX;
output[7:0] data_out;
output en_data_out;
reg[7:0] data_out;
reg en_data_out;
reg[7:0] state;//存储状态
reg[12:0] con;//时间计数
reg[3:0] con_bits;//空闲计数
reg RX_delay;//RX延时
always@(posedge clk or negedge res) begin
if(~res) begin//复位
state<=0;
con<=0;
con_bits<=0;
en_data_out<=0;
data_out<=0;
RX_delay<=0;
end
else begin
RX_delay<=RX;
case(state)
0:begin//状态0,等待,4999个con为一个数据间隔
if(con==4999) begin
con<=0;
end
else begin
con<=con+1;
end
if(con==0) begin
if(RX) begin
con_bits<=con_bits+1;
end
else begin
con_bits<=0;
end
end
if(con_bits==12) begin//十二个数据间隔后进入状态1
state<=1;
end
end
1:begin//????
en_data_out<=0;
if(~(RX&RX_delay)) begin
state<=2;
end
end
2:begin//等待1.5个数据间隔后接受b0
if(con==7500-1) begin
con<=0;
data_out[0]<=RX;
state<=3;
end
else begin
con<=con+1;
end
end
3:begin//一个数据间隔后接收b1
if(con==5000-1) begin
con<=0;
data_out[1]<=RX;
state<=4;
end
else begin
con<=con+1;
end
end
4:begin//接收b2
if(con==5000-1) begin
con<=0;
data_out[2]<=RX;
state<=5;
end
else begin
con<=con+1;
end
end
5:begin//接收b3
if(con==5000-1) begin
con<=0;
data_out[3]<=RX;
state<=6;
end
else begin
con<=con+1;
end
end
6:begin//接收b4
if(con==5000-1) begin
con<=0;
data_out[4]<=RX;
state<=7;
end
else begin
con<=con+1;
end
end
7:begin//接收b5
if(con==5000-1) begin
con<=0;
data_out[5]<=RX;
state<=8;
end
else begin
con<=con+1;
end
end
8:begin//接收b6
if(con==5000-1) begin
con<=0;
data_out[6]<=RX;
state<=9;
end
else begin
con<=con+1;
end
end
9:begin//接收b7
if(con==5000-1) begin
con<=0;
data_out[7]<=RX;
state<=10;
end
else begin
con<=con+1;
end
end
10:begin
en_data_out<=1;//data_out使能
state<=1;//返回状态1,
end
default:begin//规定状态之外的状态
state<=0;
con<=0;
con_bits<=0;
en_data_out<=0;
end
endcase
end
end
endmodule
module uart_rxer_tb;
reg clk,res;
wire RX;
wire[7:0] data_out;
wire en_data_out;
reg[25:0] RX_send;//发送的数据
reg[12:0] con;//????bit??
assign RX=RX_send[0];
uart_rxer uart_rxer(//实例化一个接收模块
.clk(clk),
.res(res),
.RX(RX),
.data_out(data_out),
.en_data_out(en_data_out)
);
initial begin
clk<=0;res<=0;RX_send<={1'b1,8'haa,1'b0,16'hffff};con<=0;//为数据赋值
#17 res<=1;
#4000000 $stop;
end
always #5 clk<=~clk;
always@(posedge clk) begin
if(con==5000-1) begin//4999为一个数据间隔
con<=0;
end
else begin
con<=con+1;
end
if(con==0) begin//每一个数据间隔
RX_send[24:0]<=RX_send[25:1];//RX_send按位循环
RX_send[25]<=RX_send[0];
end
end
endmodule
仿真结果: