在UART(一)中主要解决的是单字节的发送和接受,但是单字节的应用场景相对较小。在大多数场景下,串口都是用于连续多字节的收发工作。 因此,本篇文章将基于已有的单字节串口收发模块,结合上一章学习的状态机,完成多字节串口发送模块和多字节串口接收模块的设计,并通过仿真和板级测试对设计进行验证,完成多字节串口收发的验证。
一、多字节发送(Tx_bytes)
1.1Verilog 代码:
例化UART(一)的单字节发送模块
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Description: 串口多字节发送
//////////////////////////////////////////////////////////////////////////////////
module uart_bytes_tx#(
parameter DATA_WIDTH = 32
)(
Clk ,
Rst_n ,
data_bytes ,
send_en ,
Baud_Set ,
uart_tx ,
Tx_Done ,
uart_state
);
input Clk ; //模块全局时钟输入,50M
input Rst_n ; //复位信号输入,低有效
input [DATA_WIDTH - 1:0] data_bytes ; //待传输 多字节 数据
input send_en ; //发送使能
input [2:0] Baud_Set ; //波特率设置
output uart_tx ; //串口输出信号
output reg Tx_Done ; //数据发送完成标志
output uart_state ; //发送数据状态
reg [3:0] state,n_state ;
reg [7:0] cnt ;
reg [DATA_WIDTH - 1:0] r_data_bytes ;
reg [7:0] data_byte ;
reg send_byte_en ;
wire byte_tx_done ;
wire uart_tx ;
wire uart_state ;
//********** 单字节数据发送模块例化 *******\\
uart_tx_byte uart_tx_byte_u0(
.Clk (Clk ),
.Rst_n (Rst_n ),
.data_byte (data_byte ),
.send_en (send_byte_en),
.Baud_Set (Baud_Set ),
.uart_tx (uart_tx ),
.Tx_Done (byte_tx_done),
.uart_state (uart_state )
);
localparam S0 = 4'b0001, //等待发送使能(初始态)
S1 = 4'b0010, //准备数据
S2 = 4'b0100, //等待单字节数据发送完成
S3 = 4'b1000; //检查所有数据是否发送完成
//************** 状态机 ***************\\
always @(posedge Clk or negedge Rst_n) begin
if(!Rst_n)
state <= S0;
else
state <= n_state;
end
always @(*) begin
case (state)
S0: if(send_en)
n_state <= S1;
else
n_state <= S0;
S1: n_state <= S2;
S2: if(byte_tx_done)
n_state <= S3;
else
n_state <= S2;
S3: if(cnt >= DATA_WIDTH - 8)
n_state <= S0;
else
n_state <= S1;
default:n_state <= S0;
endcase
end
always @(posedge Clk or negedge Rst_n) begin
if(!Rst_n)
r_data_bytes <= 'd0;
else if(state