FPGA——异步串行通信(UART)接收
Posted cnlntr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FPGA——异步串行通信(UART)接收相关的知识,希望对你有一定的参考价值。
程序代码:
module uart_byte_rx(
clk ,//50MHz时钟
rst_n ,//复位
baud_set ,//波特率设置
rs232_rx ,//rs232数据接收
data_byte ,//并行数据输出
rx_done //单个字节接收完标志
);
//参数定义s
parameter DATA_W = 8;
parameter BAUS_W = 3;
parameter DABS_W = 3;
parameter BAUV_W = 13;
parameter CNTB_W = 8;
parameter RDAB_W = 3;
parameter RDAB_N = 8;
//输入信号定义
input clk ;
input rst_n ;
input [BAUS_W-1:0] baud_set ;
input rs232_rx ;
//输出信号定义
output[DATA_W-1:0] data_byte ;
output rx_done ;
//输出信号定义
reg [DATA_W-1:0] data_byte ;
wire rx_done ;
//中间信号定义
reg uart_state ;//串口接收状态
reg [DABS_W-1:0] data_byt_syn;
wire nedge ;
reg [BAUV_W-1:0] baud_div ;//波特率分频值
reg [BAUV_W-1:0] cnt_div ;//分频计数器
wire add_cnt_div ;
wire end_cnt_div ;
reg [CNTB_W-1:0] cnt_byt ;
wire add_cnt_byt ;
wire end_cnt_byt ;
reg [RDAB_W-1:0] start_bit ;
reg [RDAB_W-1:0] stop_bit ;
reg [RDAB_W-1:0] r_data_byte[RDAB_N-1:0];//RDAB_N寄存器,每个寄存器位宽为RDAB_W
//接入两个D触发器,对异步数据进行同步化处理
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
data_byt_syn <= 0;
end
else begin
data_byt_syn <= {data_byt_syn[1:0],rs232_rx};
end
end
assign nedge = (data_byt_syn[2:1] == 2‘b10);
always@(posedge clk or negedge rst_n)begin
if(rst_n==1‘b0)begin
uart_state <= 0;
end
else if(nedge) begin
uart_state <= 1;//检测到起始位0
end
else if(end_cnt_byt)begin
uart_state <= 0;
end
end
always@(posedge clk or negedge rst_n)begin
if(rst_n==1‘b0)begin
baud_div <= 0;
end
else begin
//取16个采样点
case (baud_set)
0 : baud_div <= 13‘d5208;//600bps/16
1 : baud_div <= 13‘d2604;//1200bps/16
2 : baud_div <= 13‘d1302;//2400bps/16
3 : baud_div <= 13‘d651 ;//4800bps/16
4 : baud_div <= 13‘d325 ;//9600bps/16
5 : baud_div <= 13‘d163 ;//19200bps/16
6 : baud_div <= 13‘d81 ;//38400bps/16
7 : baud_div <= 13‘d54 ;//57600bps/16
default:
baud_div <= 0;
endcase
end
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_div <= 0;
end
else if(add_cnt_div)begin
if(end_cnt_div)
cnt_div <= 0;
else
cnt_div <= cnt_div + 1‘b1;
end
end
assign add_cnt_div = (uart_state == 1);
assign end_cnt_div = add_cnt_div && cnt_div == baud_div-1 ;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_byt <= 0;
end
else if(add_cnt_byt)begin
if(end_cnt_byt)
cnt_byt <= 0;
else
cnt_byt <= cnt_byt + 1‘b1;
end
end
assign add_cnt_byt = (end_cnt_div == 1);
assign end_cnt_byt = (add_cnt_byt && cnt_byt == 160-1) || (start_bit > 2);//10个比特,每个比特采样16个点
always@(posedge clk or negedge rst_n)begin
if(rst_n==1‘b0)begin
start_bit <= 0;
r_data_byte[0] <= 0;
r_data_byte[1] <= 0;
r_data_byte[2] <= 0;
r_data_byte[3] <= 0;
r_data_byte[4] <= 0;
r_data_byte[5] <= 0;
r_data_byte[6] <= 0;
r_data_byte[7] <= 0;
stop_bit <= 0;
end
else if(uart_state) begin
case (cnt_byt)
//在16个点中,取样中间6个点
5,6,7,8,9,10 : start_bit <= start_bit + rs232_rx;
21,22,23,24,25,26 : r_data_byte[0] <= r_data_byte[0] + rs232_rx;
37,38,39,40,41,42 : r_data_byte[1] <= r_data_byte[1] + rs232_rx;
53,54,55,56,57,58 : r_data_byte[2] <= r_data_byte[2] + rs232_rx;
69,70,71,72,73,74 : r_data_byte[3] <= r_data_byte[3] + rs232_rx;
85,86,87,88,89,90 : r_data_byte[4] <= r_data_byte[4] + rs232_rx;
101,102,103,104,105,106 : r_data_byte[5] <= r_data_byte[5] + rs232_rx;
117,118,119,120,121,122 : r_data_byte[6] <= r_data_byte[6] + rs232_rx;
133,134,135,136,137,138 : r_data_byte[7] <= r_data_byte[7] + rs232_rx;
149,150,151,152,153,154 : stop_bit <= stop_bit + rs232_rx;
default: begin
start_bit <= start_bit;
r_data_byte[0] <= r_data_byte[0];
r_data_byte[1] <= r_data_byte[1];
r_data_byte[2] <= r_data_byte[2];
r_data_byte[3] <= r_data_byte[3];
r_data_byte[4] <= r_data_byte[4];
r_data_byte[5] <= r_data_byte[5];
r_data_byte[6] <= r_data_byte[6];
r_data_byte[7] <= r_data_byte[7];
stop_bit <= stop_bit;
end
endcase
end
else begin
start_bit <= 0;
r_data_byte[0] <= 0;
r_data_byte[1] <= 0;
r_data_byte[2] <= 0;
r_data_byte[3] <= 0;
r_data_byte[4] <= 0;
r_data_byte[5] <= 0;
r_data_byte[6] <= 0;
r_data_byte[7] <= 0;
stop_bit <= 0;
end
end
always@(posedge clk or negedge rst_n)begin
if(rst_n==1‘b0)begin
data_byte <= 0;
end
else if(end_cnt_byt)begin
//取r_data_byte的最高位,当r_data_byte[n]中取样‘1‘的个数大于或等于4时,该比特位为1,否则为0
data_byte[0] <= r_data_byte[0][2];
data_byte[1] <= r_data_byte[1][2];
data_byte[2] <= r_data_byte[2][2];
data_byte[3] <= r_data_byte[3][2];
data_byte[4] <= r_data_byte[4][2];
data_byte[5] <= r_data_byte[5][2];
data_byte[6] <= r_data_byte[6][2];
data_byte[7] <= r_data_byte[7][2];
end
end
assign rx_done = (add_cnt_byt && cnt_byt == 160 - 1);
endmodule
验证代码:
module uart_rx_top(
clk ,
rst_n ,
rs232_rx,
//其他信号,举例led
led
);
//参数定义
parameter LED_W = 4;
parameter DAB_W = 8;
//输入信号定义
input clk ;
input rst_n ;
input rs232_rx ;
//输出信号定义
output[LED_W-1:0] led ;
//输出信号reg定义
wire [LED_W-1:0] led ;
//中间信号定义
wire [DAB_W-1:0] data_byte ;
//组合逻辑写法
assign led = data_byte[7:4];
uart_byte_rx uart_byte_rx(
.clk(clk) ,//50MHz时钟
.rst_n(rst_n) ,//复位
.baud_set(3‘d7) ,//波特率设置
.rs232_rx(rs232_rx) ,//rs232数据接收
.data_byte(data_byte) ,//并行数据输出
.rx_done() //单个字节接收完标志
);
endmodule
仿真代码:
`timescale 1 ns/ 1 ps module uart_rx_top_vlg_tst(); reg clk; reg rs232_rx; reg rst_n; // wires wire [3:0] led; uart_rx_top i1 ( .clk(clk), .led(led), .rs232_rx(rs232_rx), .rst_n(rst_n) ); initial begin clk = 0; end always begin #1 clk = ~clk; end initial begin rst_n = 0; #10; rst_n = 1; end initial begin rs232_rx = 1‘b1; #20; #1728; rs232_rx = 1‘b0; #1728; rs232_rx = 1‘b1; #1728; rs232_rx = 1‘b1; #1728; rs232_rx = 1‘b0; #1728; rs232_rx = 1‘b0; #1728; rs232_rx = 1‘b0; #1728; rs232_rx = 1‘b1; #1728; rs232_rx = 1‘b1; #1728; rs232_rx = 1‘b0; #1728; rs232_rx = 1‘b1; #100; /////////////////// #1728; rs232_rx = 1‘b0; #1728; rs232_rx = 1‘b1; #1728; rs232_rx = 1‘b0; #1728; rs232_rx = 1‘b0; #1728; rs232_rx = 1‘b0; #1728; rs232_rx = 1‘b0; #1728; rs232_rx = 1‘b1; #1728; rs232_rx = 1‘b1; #1728; rs232_rx = 1‘b0; #1728; rs232_rx = 1‘b1; end endmodule
以上是关于FPGA——异步串行通信(UART)接收的主要内容,如果未能解决你的问题,请参考以下文章