FPGA 串口通信协议
波特率:波特率就是串口的通信速率,常见的波特率有12000bps、4800bps、9600bps、115200bps、256000bps、500000bps,这里波特率的意思是每秒可以传输bit的个数,这里的5207=500000000/9600;传递一个字节需要的时间。
串口接收模块
输入为时钟、复位信号、输入数据、输出数据、数据接收完成标志
源代码:
module chuanxing_3(clk,rst_n,data_in,po_data,po_en);
input clk,rst_n;
input data_in;
output reg [7:0] po_data;
output reg po_en;
reg [2:0] state;
reg [2:0] next_state;
reg [3:0] cnt_bit;
reg [12:0] cnt;
parameter Idle=0,start=1,read=2,stop=3;
parameter TIME=5207;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
state<=Idle;
else
state<=next_state;
end
//计数模块
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt<=0;
else
begin
if(state==start||state==read||state==stop)
begin
if(cnt==TIME)
cnt<=0;
else
cnt<=cnt+1;
end
else
cnt<=0;
end
end
//传递字节
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt_bit<=0;
else
begin
if(next_state==read)
begin
if(cnt_bit==8&&cnt==TIME)
cnt_bit<=0;
else if(cnt_bit==8&&cnt<TIME)
cnt_bit<=8;
else if(cnt_bit<8&&cnt==TIME)
cnt_bit<=cnt_bit+1;
else
cnt_bit<=cnt_bit;
end
else
cnt_bit<=0;
end
end
always @(*)
begin
case(state)
Idle:
next_state=data_in?Idle:start;
start:
begin
if(cnt==TIME)
next_state=read;
else
next_state=start;
end
read:
begin
if(cnt_bit==8&&cnt==TIME)
next_state=stop;
else
next_state=read;
end
stop:
begin
if(cnt==TIME/2)
next_state=Idle;
else
next_state=stop;
end
endcase
end
//串行转并行
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
po_data<=0;
else
begin
if(next_state==read&&cnt==TIME/2)
po_data[7:0]<={po_data[6:0],data_in};
else
po_data[7:0]<=po_data[7:0];
end
end
//数据接收完成标志
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
po_en<=0;
else begin
if(state==stop&&cnt==TIME)
po_en<=1;
else
po_en<=0;
end
end
endmodule
发送模块
module chuanxing_3_tx(clk,rst_n,pi_data,pi_en,data_out);
input clk,rst_n;
input [7:0] pi_data;
input pi_en;
output reg data_out;
parameter TIME=5207;
parameter Idle=0,start=1,send=2,stop=3;
reg [3:0] cnt_bit; //9个字节
reg [12:0] cnt;
reg [2:0] state,next_state;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
state<=Idle;
else
state<=next_state;
end
always @(*)
begin
case(state)
Idle:
begin
if(pi_en)
next_state=start;
else
next_state=Idle;
end
start:
begin
if(cnt==TIME)
next_state=send;
else
next_state=start;
end
send: begin
if(cnt_bit==8&&cnt==TIME)
next_state=stop;
else
next_state=send;
end
stop:begin
if(cnt==TIME)
next_state=Idle;
else
next_state=stop;
end
endcase
end
//计数模块
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt<=0;
else
begin
if(next_state==start||next_state==send||next_state==stop)
begin
if(cnt==TIME)
cnt<=0;
else
cnt<=cnt+1;
end
else
cnt<=0;
end
end
//字节计数
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt_bit<=0;
else begin
if(next_state==stop)
cnt_bit<=0;
else if(cnt_bit<8&&next_state==send&&cnt==TIME)
cnt_bit<=cnt_bit+1;
else
cnt_bit<=cnt_bit;
end
end
//
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
data_out<=0;
else begin
if(next_state==start)
data_out<=0;
else if(next_state==stop)
data_out<=1;
else
case(cnt_bit)
4'd1: data_out<=pi_data[cnt_bit-1];
4'd2: data_out<=pi_data[cnt_bit-1];
4'd3: data_out<=pi_data[cnt_bit-1];
4'd4: data_out<=pi_data[cnt_bit-1];
4'd5: data_out<=pi_data[cnt_bit-1];
4'd6: data_out<=pi_data[cnt_bit-1];
4'd7: data_out<=pi_data[cnt_bit-1];
4'd8: data_out<=pi_data[cnt_bit-1];
endcase
end
end
endmodule