Verilog实现串口通讯(UART)
本代码参考了野火的相关教程,实现了发送和接收回环,同时可以通过串口数据控制LED灯的亮灭,在电脑发送数据时要选择HEX发送模式,发送16进制的数据进行控制。
UART协议中,在空闲时为高电平。在常用的一位停止位和无校验位的设置中,起始位为低电平,紧接着是8位的数据位,最后是一位高电平的停止位。
接收模块
接收模块的主要设计是将起始位下降沿的检测作为接收系统的开始信号,通过起始信号和bit位的计数信号相结合就可以得到一个贯穿整体运行过程的使能信号,通过对使能信号的判断就可以实现对系统的控制。
另一个关键问题是电平采集的时间,应该 在一个bit的中间位置进行采集,这样可以有效避免采集电平不稳定的问题。
接收模块的代码如下:
module uart_receive (
input clk,
input rst_n,
input uart_rx,
output reg receive_done,
output reg [7:0] uart_data
);
parameter SYSTERM_CLK = 50_000_000; //系统时钟频率
parameter UART_BPS = 115200; //串口波特率
localparam BPS_COUNT_MAX = SYSTERM_CLK/UART_BPS; //为得到指定波特率
//需要对系统时钟计数BPS_COUNT次
reg [7:0] reg_data;//接受数据缓存
reg [3:0] bit_count;//接收数据时用于计数接收到了多少位
reg [12:0] bps_count;//用于按照时钟计算一个字节的时间
reg start_bit;//检测到起始位的下降沿之后触发一个时钟的高电平
reg reg1 ;
reg reg2 ;
reg reg3 ;
reg bit_flag ;//在一个电平的中间位置产生高电平标志
reg work_en ;//在本标志位高电平时,接受工作开始,在低电平时工作结束
reg rx_flag ;//在数据缓存器存满了之后产生一个高电平
//插入两级寄存器进行数据同步,用来消除亚稳态
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
reg1 <= 1'b1;//因为UART的空闲状态是高电平,所以复位时电平要设置为高电平
end
else begin
reg1 <= uart_rx;
end
end
//插入两级寄存器进行数据同步,用来消除亚稳态
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
reg2 <= 1'b1;//因为UART的空闲状态是高电平,所以复位时电平要设置为高电平
end
else begin
reg2 <=reg1;
end
end
//插入两级寄存器进行数据同步,用来消除亚稳态
always @(posedg