uart可谓是我们最长用到的接口,包括平时调试也会例化一个出来看看数据对不对,下面就分享一个我常用的UART代码,嘎嘎香
/
// 串口接收模块
// 波特率可通过修改参数 CNT_BTL和CNT_MID 设置
// 数据位为 8bit
/
module uart_rx(
clk ,
rst_n ,
uart_rx ,
rx_vld ,
rx_data
);
//参数定义
parameter CNT_BTL = 20'd5208;
parameter CNT_MID = 20'd2604; // 该值为CNT_BTL的一半。
parameter CNT_RX = 4'd9 ;
parameter DATA_W = 8 ;
//输入信号定义
input clk ;
input rst_n ;
input uart_rx ;
//输出信号定义
output[DATA_W-1:0] rx_data ;
output rx_vld ;
//输出信号reg定义
reg [DATA_W-1:0] rx_data ;
reg rx_vld ;
//中间信号定义
reg uart_rx_r ;
reg uart_rx_r1 ;
reg uart_rx_r2 ;
reg flag ;
reg [19:0] cnt0 ;
wire add_cnt0 ;
wire end_cnt0 ;
reg [3:0] cnt1 ;
wire add_cnt1 ;
wire end_cnt1 ;
wire add_en ;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt0 <= 0;
end
else if(add_cnt0)begin
if(end_cnt0)
cnt0 <= 0;
else
cnt0 <= cnt0 + 1;
end
end
assign add_cnt0 = flag;
assign end_cnt0 = add_cnt0 && cnt0== CNT_BTL-1;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt1 <= 0;
end
else if(add_cnt1)begin
if(end_cnt1)
cnt1 <= 0;
else
cnt1 <= cnt1 + 1;
end
end
assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1 && cnt1== CNT_RX-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
uart_rx_r <= 1'b1;
uart_rx_r1 <= 1'b1;
uart_rx_r2 <= 1'b1;
end
else begin
uart_rx_r <= uart_rx;
uart_rx_r1 <= uart_rx_r;
uart_rx_r2 <= uart_rx_r1;
end
end
assign add_en = uart_rx_r2&&~uart_rx_r1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag <= 1'b0;
end
else if(add_en)begin
flag <= 1'b1;
end
else if(end_cnt1)begin
flag <= 1'b0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
rx_vld <= 1'b0;
end
else if(end_cnt1)begin
rx_vld <= 1'b1;
end
else begin
rx_vld <= 1'b0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
rx_data <= 8'b0;
end
else if(cnt1!=0&&add_cnt0&&cnt0==CNT_MID-1)begin
rx_data[cnt1-1] <= uart_rx_r2;
end
end
endmodule