FPGA串口接收
在Quartus II中,使用In system sources and probes editor工具,查看由PC端发送到UART接收模块接收到的数据.
串口接收模块
Rs232_rx为PC端发送给FPGA的数据,Data将发送的数据提供给电脑查看。Bps_set选择波特率。
将接收到的数据每一字节分为16份,读取中间6位的和,大于3的字节为1,小于3的字节为0。
将UART_TX模块加入到uart_data_rx工程中。
module UART_RX( //串口接收模块
Clk,
Rst_n,
Rs232_rx,
Bps_set,
Data_out,
Done_rx
);
input Clk;
input Rst_n;
input Rs232_rx;
input [2:0]Bps_set;
output reg [7:0]Data_out;
output reg Done_rx;
reg [8:0]bps_max;//计数值
reg now_reg0,rs232_rx_now; //同步寄存器 消除亚稳态
reg data_reg0,data_reg1; //数据寄存器 判断高低电平
wire low;
reg en_data;
reg [8:0]bps_con; //bps_clk时钟计数器
reg bps_clk;
reg [7:0]bps_count;
reg [2:0]Data[7:0]; //共有8个Data数据每一个Data数据有3位 例如110
reg [2:0]start_bite;
reg [2:0]stop_bite;
//查找表选择计数值
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
bps_max <= 9'b0;
else begin
case(Bps_set)
0: bps_max <= 9'd324; //波特率9600
1: bps_max <= 9'd162; //波特率19200
2: bps_max <= 9'd80; //波特率38400
3: bps_max <= 9'd53; //波特率57600
4: bps_max <= 9'd26; //波特率115200
default : bps_max <= 9'd324;
endcase
end
//消除亚稳态
always @(posedge Clk or negedge Rst_n)
if(!Rst_n) begin
now_reg0 <= 0;
rs232_rx_now <= 0;
end
else begin
now_reg0 <= Rs232_rx;
rs232_rx_now <= now_reg0;
end
//判断低电平
always @(posedge Clk or negedge Rst_n)
if(!Rst_n) begin
data_reg0 <= 0;
data_reg1 <= 0;
end
else begin
data_reg0 <= rs232_rx_now;
data_reg1 <= data_reg0;
end
assign low = !data_reg0 & data_reg1;
//使能开始计数
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
bps_con <= 9'b0;
else
if(en_data) begin
if(bps_con == bps_max)
bps_con <= 9'b0;
else bps_con <= bps_con + 1'b1;
end else
bps_con <= 9'b0;
//产生波特率时钟
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
bps_clk <= 0;
else if(bps_con ==9'b1)
bps_clk <= 1'b1;
else bps_clk <= 1'b0;
//计数波特率时钟
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
bps_count <= 8'b0;
else if((bps_count == 8'd159) || ((bps_count == 8'd12) && (start_bite >2)))
bps_count <= 8'b0;
else if(bps_clk)
bps_count <= bps_count + 1'b1;
//产生Done_rx计数满信号
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
Done_rx <= 1'b0;
else if(bps_count == 8'd159)
Done_rx <= 1'b1;
else Done_rx <= 1'b0;
//将Data的值给Data_out输出查看
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
Data_out <= 8'b0;
else if(bps_count == 8'd159) begin
Data_out[0] <= Data[0][2]; //如果中间6位数值和加起来大于3(100.101.110)第3位数值将大于1,由此可以将第3位的值直接传给Data_out数据
Data_out[1] <= Data[1][2];
Data_out[2] <= Data[2][2];
Data_out[3] <= Data[3][2];
Data_out[4] <= Data[4][2];
Data_out[5] <= Data[5][2];
Data_out[6] <= Data[6][2];
Data_out[7] <= Data[7][2];
end
//将Data的中间6位数据累加
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)begin
start_bite <= 3'b0;
Data[0] <= 3'b0;
Data[1] <= 3'b0;
Data[2] <= 3'b0;
Data[3] <= 3'b0;
Data[4] <= 3'b0;
Data[5] <= 3'b0;
Data[6] <= 3'b0;
Data[7] <= 3'b0;
stop_bite <= 3'b0;
end else if(bps_clk)
begin
case(bps_count)
0:begin
start_bite <= 3'b0;
Data[0] <= 3'b0;
Data[1] <= 3'b0;
Data[2] <= 3'b0;
Data[3] <= 3'b0;
Data[4] <= 3'b0;
Data[5] <= 3'b0;
Data[6] <= 3'b0;
Data[7] <= 3'b0;
stop_bite <= 3'b0;
end
6,7,8,9,10,11: start_bite <= start_bite + rs232_rx_now;
22,23,24,25,26,27: Data[0] <= Data[0] + rs232_rx_now;
38,39,40,41,42,43: Data[1] <= Data[1] + rs232_rx_now;
54,55,56,57,58,59: Data[2] <= Data[2] + rs232_rx_now;
70,71,72,73,74,75: Data[3] <= Data[3] + rs232_rx_now;
86,87,88,89,90,91: Data[4] <= Data[4] + rs232_rx_now;
102,103,104,105,106,107: Data[5] <= Data[5] + rs232_rx_now;
118,119,120,121,122,123: Data[6] <= Data[6] + rs232_rx_now;
134,135,136,137,138,139: Data[7] <= Data[7] + rs232_rx_now;
150,151,152,153,154,155: stop_bite <= stop_bite + rs232_rx_now;
default : begin
start_bite <= start_bite;
Data[0] <= Data[0];
Data[1] <= Data[1];
Data[2] <= Data[2];
Data[3] <= Data[3];
Data[4] <= Data[4];
Data[5] <= Data[5];
Data[6] <= Data[6];
Data[7] <= Data[7];
stop_bite <= stop_bite;
end
endcase
end
//判断是否完成接收或无开始错误,产生使能信号
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
en_data <= 1'b0;
else if(low)
en_data <= 1'b1;
else if(Done_rx ||((bps_count == 8'd12) && (start_bite >2)))
en_data <= 1'b0;
else en_data <= en_data;
endmodule
串口接收仿真模块
将UART_TX 模块添加到工程中。
`timescale 1ns/1ns
`define clk_period 20
module uart_rx_tb;
reg Clk;
reg Rst_n;
reg [2:0]Bps_set;
reg Con_en;
reg [7:0]Data_in;
wire Rs232_tx;
wire Done_tx;
wire Uart_state;
wire [7:0]Data;
wire Done_rx;
UART_TX UART_TX0( //发送模块
.Clk(Clk),
.Rst_n(Rst_n),
.Bps_set(Bps_set),
.Con_en(Con_en),
.Data_in(Data_in), //将数据传送到发送模块
.Rs232_tx(Rs232_tx), //发送Data_in数据给接收模块
.Done_tx(Done_tx), //发送完成标志位
.Uart_state(Uart_state)
);
uart_data_rx uart_data_rx0( //串口接收模块
.Clk(Clk),
.Rst_n(Rst_n),
.Rs232_rx(Rs232_tx),
.Bps_set(Bps_set),
.Data_out(Data), //将接收到的信号发送出来
.Done_rx(Done_rx)
);
initial Clk = 1;
always #(`clk_period/2) Clk = ~Clk;
initial begin
Rst_n = 1'b0;
Data_in = 8'b0;
Con_en = 1'b0;
Bps_set = 3'd4;
#(`clk_period*20+1);
Rst_n = 1'b1;
#(`clk_period*20+1);
Data_in = 8'hae;
Con_en = 1'b1;
#(`clk_period);
Con_en = 1'b0;
@(posedge Done_tx)
#(`clk_period*2000);
Data_in = 8'h5b;
Con_en = 1'b1;
#(`clk_period);
Con_en = 1'b0;
@(posedge Done_tx)
#(`clk_period*2000);
$stop;
end
endmodule
仿真结果
顶层模块
module uart_top(
Clk,
Rst_n,
Rs232_rx
);
input Clk;
input Rst_n;
input Rs232_rx;
reg [7:0]Data_r;
wire [7:0]Data;
wire Done_rx;
uart_data_rx uart_data_rx1( //串口接收模块
.Clk(Clk),
.Rst_n(Rst_n),
.Rs232_rx(Rs232_rx),
.Bps_set(3'b0),
.Data_out(Data), //将接收到的信号发送出来
.Done_rx(Done_rx)
);
is is0 (
.probe(Data_r),
.source()
);
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
Data_r <= 0 ;
else if(Done_rx)
Data_r <= Data;
else
Data_r <= Data_r;
endmodule
使用tool工具
时时将接收到的数据展示到PC端。