一、串口简介
通用异步收发传输器,英文全称Universal Asynchronous Receiver/Transmitter,简称UART。
UART是一种通用的数据通信协议,也是异步串行通信口(串口)的总称,它在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换成并行数据。
包括RS232、RS499、RS423、RS422和RS485等接口标准规范和总线标准规范。
二、RS232
1.通信方式
有两个模块,tx(发送模块) 和 rx(接受模块)
RS232的传输距离比较近,传输速率比较慢。
2.RS232接口
数据接收和发送的数据帧!!!!
波特率:来波特率指数据信号对载波的调制速率,它用单位时间内载波调制状态改变次数来表示,其单位为波特(Baud),Bps
比特率:比特率是每秒传输的比特数。单位为比特(bps位/秒)
波特率源与比特率的关系为:比特率=波特率 * 单个调制状态对应的二进制位数
串口发或接收1bit数据的一个时间,称之为波特。例如: 波特率为9600Bps的波特率,其对应的1个波特为(1/9600)s 若系统时钟为100MHz,则时钟周期为10ns,那么在9600波特率下,一个波特等于几个时钟周期?
(1x109)
÷
9600
÷
10
≈
\div 9600 \div 10 \approx
÷9600÷10≈ 10,416
三、代码及仿真
1.RX模块
RX.v
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2021/09/03 12:36:32
// Design Name:
// Module Name: uart_rx
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module uart_rx
#(
parameter UART_BPS = 'd9600,
parameter CLK_FREQ = 'd100_000_000
)
(
input wire sys_clk ,
input wire rst_n ,
input wire rx ,
output reg [7:0] Po_data ,
output reg Po_flag
);
parameter BAUD_CNT_MAX = CLK_FREQ/UART_BPS;
reg rx_reg1; // 同步到系统时钟下
reg rx_reg2;
reg rx_reg3; // 打两拍,减小亚稳态危害
reg Start_flag; // 开始一个数据帧的传输标志信号
reg Work_en; // 标识数据采集范围,接收数据工作使能信号
reg [15:0] baud_cnt; // 计数1码元所需要的时钟周期数(在本实验中,1码元=1bit)
reg Bit_flag; // 每bit数据稳定点拉高一拍
reg [3:0] Bit_cnt; // bit计数器
reg [7:0] rx_data;
reg rx_flag;
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
// reset
rx_reg1 <= 1'b1;
rx_reg2 <= 1'b1;
rx_reg3 <= 1'b1;
end
else begin
rx_reg1 <= rx;
rx_reg2 <= rx_reg1;
rx_reg3 <= rx_reg2;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
Start_flag <= 1'b0;
end
else if ((rx_reg3 == 1'b1) && (rx_reg2 == 1'b0) && (Work_en == 1'b0)) begin
Start_flag <= 1'b1;
end
else begin
Start_flag <= 1'b0;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
Work_en <= 1'b0;
end
else if (Start_flag == 1'b1) begin
Work_en <= 1'b1;
end
else if ((Bit_cnt == 4'd8) && (Bit_flag == 1'b1)) begin
Work_en <= 1'b0;
end
else begin
Work_en <= Work_en;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
baud_cnt <= 16'd0;
end
else if ((baud_cnt == BAUD_CNT_MAX - 1) || (~Work_en)) begin
baud_cnt <= 16'd0;
end
else begin
baud_cnt <= baud_cnt + 1'b1;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
Bit_flag <= 1'b0;
end
else if (baud_cnt == BAUD_CNT_MAX / 2 - 1) begin
Bit_flag <= 1'b1;
end
else begin
Bit_flag<= 1'b0;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
Bit_cnt <= 1'b0;
end
else if ((Bit_flag) && (Bit_cnt == 4'd8)) begin
Bit_cnt <= 1'b0;
end
else if (Bit_flag) begin
Bit_cnt <= Bit_cnt + 1'b1;
end
else begin
Bit_cnt <= Bit_cnt;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rx_data <= 8'd0;
end
else if (((Bit_cnt >= 4'd1) && (Bit_cnt <= 4'd8)) && (Bit_flag == 1'b1))begin
rx_data <= {rx_reg3,rx_data[7:1]};
end
else begin
rx_data <= rx_data;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rx_flag <= 1'b0;
end
else if ((Bit_cnt == 4'd8) && (Bit_flag == 1'b1)) begin
rx_flag <= 1'b1;
end
else
rx_flag <= 1'b0;
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
Po_data <= 8'd0;
end
else if (rx_flag == 1'b1) begin
Po_data <= rx_data;
end
else begin
Po_data <= Po_data;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
Po_flag <= 1'd0;
end
else begin
Po_flag <= rx_flag;
end
end
endmodule
tb_rx.v
`timescale 1ns / 1ns
//
// Company:
// Engineer:
//
// Create Date: 2021/09/03 20:53:28
// Design Name:
// Module Name: tb_rx
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module tb_rx();
reg sys_clk;
reg rst_n;
reg rx;
wire [7:0] Po_data;
wire Po_flag;
initial begin
sys_clk <= 1'b1;
rst_n <= 1'b0;
rx <= 1;
#10
rst_n <= 1'b1;
end
initial begin
#100
rx_bit(8'd0);
rx_bit(8'd1);
rx_bit(8'd2);
rx_bit(8'd3);
rx_bit(8'd4);
rx_bit(8'd5);
rx_bit(8'd6);
rx_bit(8'd7);
rx_bit(8'b1010_0111);
end
always #5 sys_clk = ~sys_clk;
task rx_bit ;
input [7:0] data;
integer i;
begin
for(i = 0; i < 10; i = i + 1)begin
case(i)
0:rx <= 1'b0;
1:rx <= data[0];
2:rx <= data[1];
3:rx <= data[2];
4:rx <= data[3];
5:rx <= data[4];
6:rx <= data[5];
7:rx <= data[6];
8:rx <= data[7];
9:rx <= 1'b1;
default:rx <= 1'b1;
endcase
#(10416*10);
end
end
endtask
uart_rx
#(
.UART_BPS (9600 ),
.CLK_FREQ (100_000_000 )
)uart_rx_inst
(
.sys_clk(sys_clk),
.rst_n (rst_n),
.rx (rx),
.Po_data(Po_data),
.Po_flag(Po_flag)
);
endmodule
仿真波形图
2.TX模块
tx.v
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2021/09/04 19:36:40
// Design Name:
// Module Name: uart_tx
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module uart_tx
#(
parameter UART_BPS = 'd9600,
parameter CLK_FREQ = 'd100_000_000
)
(
input wire sys_clk ,
input wire rst_n ,
input wire [7:0] Pi_data ,
input wire Pi_flag ,
output reg tx
);
parameter BAUD_CNT_MAX = CLK_FREQ/UART_BPS;
reg Work_en ;
reg [15:0] baud_cnt ;
reg [3:0] Bit_cnt ;
reg Bit_flag ;
always @(posedge sys_clk or negedge rst_n)begin
if (rst_n == 1'b0) begin
Work_en <= 1'b0;
end
else if (Pi_flag == 1'b1) begin
Work_en <= 1'b1;
end
else if ((Bit_cnt == 4'd9) && (Bit_flag == 1'b1)) begin
Work_en <= 1'b0;
end
else begin
Work_en <= Work_en;
end
end
always @(posedge sys_clk or negedge rst_n)begin
if (rst_n == 1'b0) begin
baud_cnt <= 16'd0;
end
else if ((baud_cnt == BAUD_CNT_MAX - 1'b1) || (~Work_en)) begin
baud_cnt <= 16'd0;
end
else begin
baud_cnt <= baud_cnt + 1'b1;
end
end
always @(posedge sys_clk or negedge rst_n)begin
if (rst_n == 1'b0) begin
Bit_flag <= 1'b0;
end
else if (baud_cnt == 16'd1) begin
Bit_flag <= 1'b1;
end
else begin
Bit_flag <= 1'b0;
end
end
always @(posedge sys_clk or negedge rst_n)begin
if (rst_n == 1'b0) begin
Bit_cnt <= 1'b0;
end
else if ((Bit_cnt == 4'd9) && (Bit_flag == 1'b1)) begin
Bit_cnt <= 4'd0;
end
else if ((Bit_flag == 1'b1) && (Work_en == 1'b1)) begin
Bit_cnt <= Bit_cnt + 1'b1;
end
else begin
Bit_cnt <= Bit_cnt;
end
end
always @(posedge sys_clk or negedge rst_n)begin
if (rst_n == 1'b0) begin
tx <= 1'b1;
end
else if (Bit_flag == 1'b1) begin
case(Bit_cnt)
0 : tx <= 1'b0;
1 : tx <= Pi_data[0];
2 : tx <= Pi_data[1];
3 : tx <= Pi_data[2];
4 : tx <= Pi_data[3];
5 : tx <= Pi_data[4];
6 : tx <= Pi_data[5];
7 : tx <= Pi_data[6];
8 : tx <= Pi_data[7];
9 : tx <= 1'b1;
default:tx<=1'b1;
endcase
end
end
endmodule
tb_tx…v
`timescale 1ns / 1ns
//
// Company:
// Engineer:
//
// Create Date: 2021/09/04 19:39:56
// Design Name:
// Module Name: tb_tx
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module tb_tx();
reg sys_clk;
reg rst_n;
reg [7:0] Pi_data;
reg Pi_flag;
wire tx;
initial begin
sys_clk <= 1'b1;
rst_n <= 1'b0;
#10
rst_n <= 1'b1;
end
always #5 sys_clk = ~sys_clk;
initial begin
Pi_data <= 8'd0;
Pi_flag <=1'b0;
#100
//数据0
Pi_data <=8'd0;
Pi_flag <=1'b1;
#10
Pi_flag <=1'b0;
#(10416*10*10)
//数据1
Pi_data <=8'd1;
Pi_flag <=1'b1;
#10
Pi_flag <=1'b0;
#(10416*10*10)
//数据2
Pi_data <=8'd2;
Pi_flag <=1'b1;
#10
Pi_flag <=1'b0;
#(10416*10*10)
//数据3
Pi_data <=8'd3;
Pi_flag <=1'b1;
#10
Pi_flag <=1'b0;
#(10416*10*10)
//数据4
Pi_data <=8'd4;
Pi_flag <=1'b1;
#10
Pi_flag <=1'b0;
#(10416*10*10)
//数据5
Pi_data <=8'd5;
Pi_flag <=1'b1;
#10
Pi_flag <=1'b0;
#(10416*10*10)
//数据6
Pi_data <=8'd6;
Pi_flag <=1'b1;
#10
Pi_flag <=1'b0;
#(10416*10*10)
//数据7
Pi_data <=8'd7;
Pi_flag <=1'b1;
#10
Pi_flag <=1'b0;
end
uart_tx
#(
.UART_BPS (9600 ),
.CLK_FREQ (100_000_000 )
)uart_tx_inst
(
.sys_clk(sys_clk),
.rst_n (rst_n),
.Pi_data(Pi_data),
.Pi_flag(Pi_flag),
.tx (tx)
);
endmodule
仿真波形图
3.顶层模块
`timescale 1ns / 1ns
//
// Company:
// Engineer:
//
// Create Date: 2021/09/04 21:59:02
// Design Name:
// Module Name: rs232
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module rs232
(
input wire sys_clk ,
input wire rst_n ,
input wire rx ,
output wire tx
);
wire [7:0] rx_data;
wire rx_flag;
uart_tx
#(
.UART_BPS (9600 ),
.CLK_FREQ (100_000_000 )
)uart_tx_inst
(
.sys_clk(sys_clk),
.rst_n (rst_n),
.Pi_data(rx_data),
.Pi_flag(rx_flag),
.tx (tx)
);
uart_rx
#(
.UART_BPS (9600 ),
.CLK_FREQ (100_000_000 )
)uart_rx_inst
(
.sys_clk(sys_clk),
.rst_n (rst_n),
.rx (rx),
.Po_data(rx_data),
.Po_flag(rx_flag)
);
endmodule