这次设计一个多字节(8-256位)且波特率可更改(通过修改例化模块的参数)的串口发送模块。
1、状态机的设定
- 状态机的设定有空闲、发送、和数据移位三个状态,其中空闲状态为等待多字节发送的信号;
- 发送状态为给8位串口发送模块传输待发送的8位数据,同时判断是否发送完数据回到空闲状态;
- 数据移位状态为等到前面8位字节数据发送完后,将接下来待发送的8位数据移动到数据寄存器的低8位中。若数据在发送中则会进行等待;
2、需要的模块
(1)8位串口发送模块
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Lclone
//
// Create Date: 2022/12/10 00:21:40
// Design Name: uart_byte_tx
// Module Name: uart_byte_tx
// Project Name: uart_byte_tx
// Description: 8位串口发送模块,波特率可通过参数设置。
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module uart_byte_tx
#(
parameter TX_BAUD = 9600,
parameter CLK_FQC = 50_000_000,
parameter BAUD_CNT = CLK_FQC/TX_BAUD)
(
input [7:0] Data,
input Send_en,
input Clk,
input Rst_n,
output reg Uart_Tx,
output reg Tx_done
);
reg [15:0] baud_cnt;
reg [ 3:0] bit_cnt;
reg Send_en_r;
reg Send_en_rr;
reg Tx_flag;
always @(posedge Clk) begin
Send_en_r <= Send_en;
Send_en_rr <= Send_en_r;
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
Tx_flag <= 0;
else if(~Send_en_rr & Send_en_r)
Tx_flag <= 1'b1;
else if(bit_cnt == 10 - 1 & baud_cnt == BAUD_CNT - 1)
Tx_flag <= 1'b0;
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
baud_cnt <= 0;
else if(baud_cnt == BAUD_CNT - 1)
baud_cnt <= 0;
else if(Tx_flag)
baud_cnt <= baud_cnt + 1'b1;
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
bit_cnt <= 0;
else if(bit_cnt == 10 - 1 & baud_cnt == BAUD_CNT - 1)
bit_cnt <= 0;
else if(baud_cnt == BAUD_CNT - 1)
bit_cnt <= bit_cnt + 1'b1;
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
Uart_Tx <= 1'b1;
else if(Tx_flag == 0)
Uart_Tx <= 1'b1;
else case(bit_cnt)
0: Uart_Tx <= 1'b0;
1: Uart_Tx <= Data[0];
2: Uart_Tx <= Data[1];
3: Uart_Tx <= Data[2];
4: Uart_Tx <= Data[3];
5: Uart_Tx <= Data[4];
6: Uart_Tx <= Data[5];
7: Uart_Tx <= Data[6];
8: Uart_Tx <= Data[7];
9: Uart_Tx <= 1'b1;
default: Uart_Tx <= 1'b1;
endcase
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
Tx_done <= 1'b0;
else if(bit_cnt == 9 & baud_cnt == BAUD_CNT - 1)
Tx_done <= 1'b1;
else
Tx_done <= 1'b0;
end
endmodule
3、设计的模块代码
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/12/12 19:14:03
// Design Name: uart_bytes_tx
// Module Name: uart_bytes_tx_3
// Project Name: uart_bytes_tx
// Target Devices: xc7z020clg400-1
// Tool Versions: 2018.3
// Description: 多字节(8-256位)且波特率可更改(通过修改例化模块的参数)的串口发送模块。
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module uart_bytes_tx_3
#( parameter DATA_WIDTH = 40, //待发送的数据位宽
parameter ROUNDS = DATA_WIDTH/8) //数据发送的次数(例化时不需要设置)
(
input Clk, //时钟信号
input Rst_n, //复位信号
input [DATA_WIDTH-1:0] Bytes_data, //多字节数据端口
input Send_bytes_en, //多字节发送使能
output reg Tx_bytes_done, //多字节发送结束
output wire Uart_Tx //串口发送端口
);
reg [ 2:0] state; //状态寄存器
reg [DATA_WIDTH-1:0] bytes_data_reg; //多字节数据寄存器
reg [ 7:0] data_reg; //待发送的8位数据寄存器
reg se