波特率指的是异步时钟的频率。
source code
top module
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2023/04/28 15:48:05
// Design Name:
// Module Name: uart
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module uart(
input sys_clk, //外部50M时钟
input sys_rst_n, //外部复位信号,低有效
input uart_rxd, //UART接收端口
output uart_txd //UART发送端口
);
reg [7:0] fifo[7:0];
reg [2:0] read_ptr;
reg [2:0] write_ptr;
reg [7:0] send_data;
wire [7:0] uart_data;
wire send_busy;
reg send_en;
wire uart_doing;
reg uart_doing_d1,uart_doing_d0;
wire uart_doing_neg;
assign uart_doing_neg = uart_doing_d0 &!uart_doing_d1;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)begin send_en<=0; read_ptr<=3'd0;end
else
begin
if(send_en)send_en<=0;
else if(write_ptr!=read_ptr && !send_busy)
begin
send_en<=1;
send_data<=fifo[read_ptr];
read_ptr<=read_ptr+3'd1;
end
end
end
always @(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
uart_doing_d0<=0;
uart_doing_d1<=0;
end
else
begin
uart_doing_d0<=uart_doing_d1;
uart_doing_d1<=uart_doing;
end
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)write_ptr<=3'd0;
else if(uart_doing_neg &&(write_ptr+3'd1)!=read_ptr)
begin
fifo[write_ptr]<=uart_data;
write_ptr<=write_ptr+3'd1;
end
end
uart_send send1(.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.send_en(send_en),
.send_data(send_data),
.uart_txd(uart_txd),
.send_busy(send_busy));
uart_recv recv1 (.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.uart_rxd(uart_rxd),
.uart_doing(uart_doing),
.uart_data(uart_data));
endmodule
uart_send module
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2023/04/28 16:08:19
// Design Name:
// Module Name: uart_send
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module uart_send(
input sys_clk,
input sys_rst_n,
input send_en,
input [7:0] send_data,
output reg uart_txd,
output reg send_busy
);
reg [7:0] tx_data;
reg send_en_d0,send_en_d1;
wire en_neg;
parameter clk_fre=50000000;
parameter fps=115200;
parameter fps_count=clk_fre/fps;
reg [15:0] clk_count;
reg [4:0] num_count;
assign en_neg = send_en_d0 & (!send_en_d1);
always @(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
send_en_d0<=0;
send_en_d1<=0;
end
else
begin
send_en_d0<=send_en_d1;
send_en_d1<=send_en;
end
end
always @(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
send_busy<=0;
clk_count<=16'd0;
num_count<=5'd0;
end
else if(en_neg)
begin
send_busy<=1;
tx_data<=send_data;
clk_count<=16'd0;
num_count<=5'd0;
end
else if(send_busy)
begin
if(clk_count==fps_count-1)
begin
clk_count<=16'd0;
if(num_count==5'd9)begin num_count<=5'd0;send_busy<=0; end
else num_count<=num_count+1;
end
else clk_count<=clk_count+1;
end
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
uart_txd <= 1'b1;
else if (send_busy)
case(num_count)
4'd0: uart_txd <= 1'b0; //起始位
4'd1: uart_txd <= tx_data[0]; //数据位最低位
4'd2: uart_txd <= tx_data[1];
4'd3: uart_txd <= tx_data[2];
4'd4: uart_txd <= tx_data[3];
4'd5: uart_txd <= tx_data[4];
4'd6: uart_txd <= tx_data[5];
4'd7: uart_txd <= tx_data[6];
4'd8: uart_txd <= tx_data[7]; //数据位最高位
4'd9: uart_txd <= 1'b1; //停止位
default: ;
endcase
else
uart_txd <= 1'b1; //空闲时发送端口为高电平
end
endmodule
uart_recv module
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2023/04/29 09:17:28
// Design Name:
// Module Name: uart_recv
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module uart_recv(
input sys_clk, //系统时钟
input sys_rst_n, //系统复位,低电平有效
input uart_rxd, //UART接收端口
output reg uart_doing, //接收一帧数据完成标志
output reg [7:0] uart_data //接收的数据
);
reg uart_rxd_d0;
reg uart_rxd_d1;
parameter clk_fre=50000000;
parameter fps=115200;
parameter fps_count=clk_fre/fps;
reg [15:0] clk_count;
reg [4:0] num_count;
wire uart_rxd_neg;
assign uart_rxd_neg = uart_rxd_d0 & (!uart_rxd_d1);
always @(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
uart_rxd_d0<=0;
uart_rxd_d1<=0;
end
else
begin
uart_rxd_d0<=uart_rxd_d1;
uart_rxd_d1<=uart_rxd;
end
end
always @(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
clk_count<=16'd0;
num_count<=5'd0;
uart_doing<=0;
end
else if(uart_rxd_neg && !uart_doing)
begin
clk_count<=16'd1;
num_count<=5'd0;
uart_doing<=1;
end
else if(uart_doing)
begin
if(clk_count==fps_count-1)
begin
clk_count<=16'd0;
if(num_count==5'd9)begin num_count<=5'd0;end
else num_count<=num_count+1;
end
else clk_count=clk_count+1;
if(clk_count==fps_count/2)
begin
case(num_count)
4'd1: uart_data[0] <= uart_rxd; //数据位最低位
4'd2: uart_data[1] <= uart_rxd;
4'd3: uart_data[2] <= uart_rxd;
4'd4: uart_data[3] <= uart_rxd;
4'd5: uart_data[4] <= uart_rxd;
4'd6: uart_data[5] <= uart_rxd;
4'd7: uart_data[6] <= uart_rxd;
4'd8: uart_data[7] <= uart_rxd; //数据位最高位
4'd9: begin uart_doing <= 0;clk_count<=16'd0;num_count<=5'd0;end
default: ;
endcase
end
end
end
endmodule
xdc
create_clock -period 20.000 -name clk [get_ports sys_clk]
set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports sys_clk]
set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]
set_property -dict {PACKAGE_PIN T19 IOSTANDARD LVCMOS33} [get_ports uart_rxd]
set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports uart_txd]
仿真文件
仿真参考意义不大,真正调试还得看开ILA。
uart_recv_test
module uart_recv_test;
reg sys_clk;
reg sys_rst_n;
reg uart_rxd;
wire uart_doing;
wire [7:0] uart_data;
initial begin
sys_clk = 1'b0;
#(2);
forever
#(2) sys_clk = ~sys_clk;
end
initial begin
sys_rst_n = 1'b0;
uart_rxd = 1'b1;
#4;
sys_rst_n = 1'b1;
#4;
uart_rxd = 1'b0;
#40
uart_rxd = 1'b1;
end
uart_recv recv1 (.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.uart_rxd(uart_rxd),
.uart_doing(uart_doing),
.uart_data(uart_data)
);
endmodule
uart_send_test
module uart_test;
reg sys_clk;
reg sys_rst_n;
reg send_en;
reg [7:0] send_data;
wire uart_txd;
wire send_busy;
initial begin
sys_clk= 1'b0;
#(2);
forever
#(2) sys_clk = ~sys_clk;
end
initial
begin
sys_rst_n=0;
send_en=0;
send_data=7'd60;
#2 sys_rst_n=1;
#10 send_en=1;
#4 send_en=0;
end
uart_send send1(.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.send_en(send_en),
.send_data(send_data),
.uart_txd(uart_txd),
.send_busy(send_busy));
endmodule
标签:clk,uart,通信,send,sys,rst,RS232,reg
From: https://www.cnblogs.com/xzh-personal-issue/p/17393298.html