串口接收程序源码:
/***************************************************
* Module Name : uart_rx_logic
* Engineer : Huangruigui
* Target Device :
* Tool versions :
* Create Date :
* Revision : v1.0
* Description :
**************************************************/
module uart_rx_logic #(
parameter BAUD_SET = 16'd10416
)(
input wire sys_clk,
input wire sys_rst_n,
output reg [7:0] rx_data,
output reg rx_done,
input wire uart_rx
);
// parameter define
localparam CLK_DIV_NUM = (100_000_000/BAUD_SET) >> 4; // 对每一位数据进行16次采样,采中间6位数据进行平均运算
// reg define
reg [1:0] uart_rx_r; // uart_rx消除亚稳态寄存器
reg [1:0] uart_rx_t; // uart_rx寄存器
reg en_div_cnt; // 分频时钟计数器使能信号
reg [15:0] div_cnt; // 分频时钟计数器
reg [8:0] bps_clk_cnt; // 波特率时钟计数器
reg [2:0] r_rx_data[7:0];
reg [2:0] START_BIT,STOP_BIT;
// wire define
wire uart_rx_nege; // uart_rx下降沿
wire bps_clk;
//****************************************************
// 对uart_rx进行消除亚稳态,寄存
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
uart_rx_r <= 2'b00;
uart_rx_t <= 2'b00;
end
else
begin
uart_rx_r <= {uart_rx_r[0],uart_rx};
uart_rx_t <= {uart_rx_t[0],uart_rx_r[1]};
end
end
assign uart_rx_nege = uart_rx_t[1] & ~uart_rx_t[0];
//****************************************************
// gen baud clk
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
div_cnt <= 16'd0;
else if(en_div_cnt)
begin
if(div_cnt >= CLK_DIV_NUM)
div_cnt <= 16'd0;
else
div_cnt <= div_cnt + 1'b1;
end
else
div_cnt <= 16'd0;
end
assign bps_clk = (div_cnt == 16'd1);
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
bps_clk_cnt <= 9'd0;
else if((bps_clk_cnt == 9'd159) | (bps_clk_cnt == 9'd12 && (START_BIT>2)))
bps_clk_cnt <= 9'd0;
else if(bps_clk)
bps_clk_cnt <= bps_clk_cnt + 1'b1;
end
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
en_div_cnt <= 0;
else if((bps_clk_cnt == 9'd159) | (bps_clk_cnt == 9'd12 && (START_BIT>2)))
en_div_cnt <= 0;
else if(uart_rx_nege)
en_div_cnt <= 1;
end
//***********************************************
// rx_data porcess
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
rx_done <= 0;
else
rx_done <= (bps_clk_cnt == 9'd159);
end
//assign rx_done = (bps_clk_cnt == 9'd159);
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
rx_data <= 8'd0;
else if(bps_clk_cnt == 9'd159)
rx_data[0] <= r_rx_data[0][2];
rx_data[1] <= r_rx_data[1][2];
rx_data[2] <= r_rx_data[2][2];
rx_data[3] <= r_rx_data[3][2];
rx_data[4] <= r_rx_data[4][2];
rx_data[5] <= r_rx_data[5][2];
rx_data[6] <= r_rx_data[6][2];
rx_data[7] <= r_rx_data[7][2];
end
always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)begin
START_BIT <= 3'd0;
r_rx_data[0] <= 3'd0;
r_rx_data[1] <= 3'd0;
r_rx_data[2] <= 3'd0;
r_rx_data[3] <= 3'd0;
r_rx_data[4] <= 3'd0;
r_rx_data[5] <= 3'd0;
r_rx_data[6] <= 3'd0;
r_rx_data[7] <= 3'd0;
STOP_BIT <= 3'd0;
end
else if(bps_clk)begin
case(bps_clk_cnt)
0:begin
START_BIT <= 3'd0;
r_rx_data[0] <= 3'd0;
r_rx_data[1] <= 3'd0;
r_rx_data[2] <= 3'd0;
r_rx_data[3] <= 3'd0;
r_rx_data[4] <= 3'd0;
r_rx_data[5] <= 3'd0;
r_rx_data[6] <= 3'd0;
r_rx_data[7] <= 3'd0;
STOP_BIT <= 3'd0;
end
6,7,8,9,10,11: START_BIT <= START_BIT + uart_rx_r[1];
22,23,24,25,26,27: r_rx_data[0] <= r_rx_data[0] + uart_rx_r[1];
38,39,40,41,42,43: r_rx_data[1] <= r_rx_data[1] + uart_rx_r[1];
54,55,56,57,58,59: r_rx_data[2] <= r_rx_data[2] + uart_rx_r[1];
70,71,72,73,74,75: r_rx_data[3] <= r_rx_data[3] + uart_rx_r[1];
86,87,88,89,90,91: r_rx_data[4] <= r_rx_data[4] + uart_rx_r[1];
102,103,104,105,106,107:r_rx_data[5] <= r_rx_data[5] + uart_rx_r[1];
118,119,120,121,122,123:r_rx_data[6] <= r_rx_data[6] + uart_rx_r[1];
134,135,136,137,138,139:r_rx_data[7] <= r_rx_data[7] + uart_rx_r[1];
150,151,152,153,154,155:STOP_BIT <= STOP_BIT + uart_rx_r[1];
default:
begin
START_BIT <= START_BIT;
r_rx_data[0] <= r_rx_data[0];
r_rx_data[1] <= r_rx_data[1];
r_rx_data[2] <= r_rx_data[2];
r_rx_data[3] <= r_rx_data[3];
r_rx_data[4] <= r_rx_data[4];
r_rx_data[5] <= r_rx_data[5];
r_rx_data[6] <= r_rx_data[6];
r_rx_data[7] <= r_rx_data[7];
STOP_BIT <= STOP_BIT;
end
endcase
end
//*********************************************
endmodule
//***************文件结束************************
串口发送程序源码:
/***************************************************
* Module Name : uart_tx_logic
* Engineer : Huangruigui
* Target Device :
* Tool versions :
* Create Date :
* Revision : v1.0
* Description :
**************************************************/
module uart_tx_logic #(
parameter BAUD_SET = 16'd10416
)(
input wire sys_clk,
input wire sys_rst_n,
input wire tx_en,
input wire [7:0] tx_data,
output reg tx_done,
output reg uart_tx
);
// parameter define
localparam CLK_DIV_NUM = 100_000_000/BAUD_SET;
localparam START_BIT = 1'b0,
STOP_BIT = 1'b1;
// reg define
reg en_div_cnt;
reg [15:0] div_cnt;
reg [6:0] bps_clk_cnt;
reg [7:0] tx_data_t;
// wire define
wire bps_clk;
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
tx_data_t <= 0;
else if(tx_en)
tx_data_t <= tx_data;
end
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
en_div_cnt <= 0;
else if(tx_en)
en_div_cnt <= 1;
else if(tx_done)
en_div_cnt <= 0;
end
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
div_cnt <= 0;
else if(en_div_cnt)
begin
if(div_cnt >= CLK_DIV_NUM)
div_cnt <= 0;
else
div_cnt <= div_cnt + 1'b1;
end
else
div_cnt <= 0;
end
assign bps_clk = (div_cnt == 16'd1);
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
bps_clk_cnt <= 0;
else if(tx_done)
bps_clk_cnt <= 0;
else if(bps_clk)
bps_clk_cnt <= bps_clk_cnt + 1'b1;
end
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
tx_done <= 0;
else if(bps_clk_cnt == 4'd11)
tx_done <= 1'b1;
else
tx_done <= 0;
end
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
uart_tx <= 1;
else
begin
case(bps_clk_cnt)
0: uart_tx <= 1'b1;
1: uart_tx <= START_BIT;
2: uart_tx <= tx_data_t[0];
3: uart_tx <= tx_data_t[1];
4: uart_tx <= tx_data_t[2];
5: uart_tx <= tx_data_t[3];
6: uart_tx <= tx_data_t[4];
7: uart_tx <= tx_data_t[5];
8: uart_tx <= tx_data_t[6];
9: uart_tx <= tx_data_t[7];
10:uart_tx <= STOP_BIT;
default:uart_tx <= 1'b1;
endcase
end
end
endmodule
//**********文件结束****************************
串口发送接收测试程序:
// 串口发送接收模块仿真测试
`timescale 1ns/1ns
module uart_tx_rx_tb;
// parameter define
localparam BAUD_SET = 16'd10416;
reg sys_clk;
reg sys_rst_n;
reg tx_en;
reg [7:0] tx_data;
wire uart_tx;
wire rx_done;
wire [7:0] rx_data;
wire tx_done;
initial sys_clk = 1;
always #5 sys_clk = ~sys_clk;
initial begin
sys_rst_n = 0;
tx_en = 0;
tx_data = 0;
#201;
sys_rst_n = 1;
#20;
@(posedge sys_clk)
#100;
repeat(10)
begin
tx_en = 1;
tx_data = tx_data + 1;
#10;
tx_en = 0;
wait(tx_done);
#100;
end
#1000;
$stop;
end
uart_rx_logic #(
.BAUD_SET ( BAUD_SET )
)uart_rx_logic(
.sys_clk ( sys_clk ),
.sys_rst_n ( sys_rst_n ),
.rx_done ( rx_done ),
.rx_data ( rx_data ),
.uart_rx ( uart_tx )
);
uart_tx_logic #(
.BAUD_SET ( BAUD_SET )
)uart_tx_logic(
.sys_clk ( sys_clk ),
.sys_rst_n ( sys_rst_n ),
.tx_en ( tx_en ),
.tx_data ( tx_data ),
.tx_done ( tx_done ),
.uart_tx ( uart_tx )
);
endmodule
这两个模块已经验证过了,没什么大问题,各位亲可以放心使用。