一、串口协议简介
二、串口数据接收
波特率:波特率表示每秒钟传送的码元符号的个数,它是对符号传输速率的一种度量
等空闲状态只需一次(保证有10bit以上的连续的1):
verilog代码:
//2023/3/30 lzp
//串口接收
`timescale 1ns/10ps
module Serial_rev(
clk,
res,
RX,
data_out,
en_data_out
);
input clk;
input res;
input RX;
output[7:0] data_out; //接收字节输出
output en_data_out; //输出使能
reg[7:0] state; //主状态机
reg[12:0] count; //计数器,计算bit宽度,24Mhz/4800=5000
reg[3:0] count_bit; //用于计算bit数
reg RX_delay; //RX的延时
reg en_data_out;
reg[7:0] data_out;
always@(posedge clk or negedge res)
if(!res) begin
state<=0;
count<=0;
count_bit<=0;
RX_delay<=0;
en_data_out<=0;
end
else begin
RX_delay<=RX;
case(state)
0://等空闲
begin
//5000次转一轮
if(count == 5000-1) begin
count<=0;
end
else begin
count<=count+1;
end
if(count == 0) begin
if(RX == 1) begin
count_bit<=count_bit+1;
end
else begin
count_bit<=0;
end
end
//到12表示到达了空闲状态
if(count_bit == 12) begin
state<=1;
end
end
1://等起始位
begin
en_data_out<=0;
if(~RX&RX_delay) begin
state<=2;
end
end
2://收最低位b0
begin
if(count == 7500-1) begin
count<=0;
data_out[0]<=RX;
state<=3;
end
else begin
count<=count+1;
end
end
3://收最低位b1
begin
if(count == 5000-1) begin
count<=0;
data_out[1]<=RX;
state<=4;
end
else begin
count<=count+1;
end
end
4://收最低位b2
begin
if(count == 5000-1) begin
count<=0;
data_out[2]<=RX;
state<=5;
end
else begin
count<=count+1;
end
end
5://收最低位b3
begin
if(count == 5000-1) begin
count<=0;
data_out[3]<=RX;
state<=6;
end
else begin
count<=count+1;
end
end
6://收最低位b4
begin
if(count == 5000-1) begin
count<=0;
data_out[4]<=RX;
state<=7;
end
else begin
count<=count+1;
end
end
7://收最低位b5
begin
if(count == 5000-1) begin
count<=0;
data_out[5]<=RX;
state<=8;
end
else begin
count<=count+1;
end
end
8://收最低位b6
begin
if(count == 5000-1) begin
count<=0;
data_out[6]<=RX;
state<=9;
end
else begin
count<=count+1;
end
end
9://收最低位b7
begin
if(count == 5000-1) begin
count<=0;
data_out[7]<=RX;
state<=10;
end
else begin
count<=count+1;
end
end
10://产生使能脉冲
begin
en_data_out<=1;
state<=1;
end
default:
begin
state<=0;
count<=0;
count_bit<=0;
en_data_out<=0;
end
endcase
end
endmodule
//testbench
module serial_rev_tb;
reg clk;
reg res;
wire RX;
wire[7:0] data_out;
wire en_data_out;
reg[25:0] RX_send; //装有串口字节数据
reg[12:0] con;
Serial_rev Serial_rev(//同名例化
clk,
res,
RX,
data_out,
en_data_out
);
assign RX=RX_send[0]; //连接RX
initial begin
clk<=0;res<=0;RX_send<={1'b1,8'h0a,1'b0,16'hffff};con<=0;
#17 res<=1;
#1000 $stop;
end
always#(5) clk=~clk;
always@(posedge clk) begin
if(con == 5000-1) begin
con<=0;
end
else begin
con<=con+1;
end
if(con == 0) begin
//循环右移
RX_send[24:0]<=RX_send[25:1];
RX_send[25]<=RX_send[0];
end
end
endmodule
三、串口数据发送
verilog代码:
//2023/3/30 lzp
//串口发送
`timescale 1ns/10ps
module Serial_send(
clk,
res,
data_in,
en_data_in,
TX,
rdy
);
input clk;
input res;
input[7:0] data_in;//准备发送的数据
input en_data_in;//发送使能
output TX;//输出数据
output rdy;//空闲标志,0表示空闲
reg[3:0] state;//状态标志
reg[9:0] send_buf;//发送缓存
reg[12:0] con;//用于计算波特周期
reg[9:0] send_flag;//用于判断右移结束
reg rdy;//0表示空闲
assign TX=send_buf[0];//连接TX到发送缓存最低位
always@(posedge clk or negedge res)
if(!res) begin
state<=0;
rdy<=0;
send_buf<=1; //因为TX空闲为1,所以sendbuf初始最低位为1
con<=0;
send_flag<=10'b10_0000_0000;
end
else begin
case(state)
0://等待发送使能
begin
if(en_data_in == 1) begin
state<=1;
end
end
1://填充发送寄存器
begin
send_buf<={1'b1,data_in,1'b0};
send_flag<=10'b10_0000_0000;
rdy<=1;
state<=2;
end
2://发送寄存器右移
begin
if(con == 5000-1) begin
con<=0;
end
else begin
con<=con+1;
end
if(con == 5000-1) begin
send_buf[8:0]<=send_buf[9:1];
send_flag[8:0]<=send_flag[9:1];
end
//发送完毕
if(send_flag[0] == 1) begin
rdy<=0;
state<=0;
end
end
endcase
end
endmodule
//testbench
module serial_send_tb;
reg clk;
reg res;
reg[7:0] data_in;
reg en_data_in;
wire TX;
wire rdy;
Serial_send Serial_send(
clk,
res,
data_in,
en_data_in,
TX,
rdy
);
initial begin
clk<=0;
res<=0;
data_in<=0;
en_data_in<=0;
data_in<=8'b1100_1100;
#17 res<=1;
#30 en_data_in<=1;
#10 en_data_in<=0;
#1000 $stop;
end
always#(5) clk=~clk;
endmodule