在串口试验中,不管是野火还是正点原子的例程,都是单字节的回环测试,无法进行多字节的发送,在野火的串口程序基础上,进行了修改,实现串口多字节的发送。
1、波形图
波形图如下,pi_flag为串口接收完成后的使能信号。
将pi_flag打1拍,延时一个时钟周期后产生pi_flag_reg1,保证数据在发送前能给到待发送数据寄存器UART_data。
pi_flag_reg1再打1拍,延时一个时钟周期后产生pi_flag_reg2,用于产生发送控制使能信号work_en,保证使能开始前数据已给到UART_data。
baud_cnt为发送计数器,波特率为9600,baud_cnt每计数5208次后发送一次数据。
bit_flag为发送使能信号,baud_cnt计数到1时产生1个时钟周期的上升沿。
bit_flag_cnt为发送数据计数器,每发送1bit数据计数一次,直到1帧数据发送完后计数器清零。
byte_tx_done为字节信号发送完毕标志信号,拉高后UART_data右移8位。
byte_tx_done为byte_tx_done1拍的信号,保证UART_data已经完成右移,拉高后将UART_data的后8位数据发送给发送缓存寄存器buffer_data。
cnt_num为发送字节计数器,由需要发送数据的字节数决定。
2、程序
module UART_tx
#(
parameter UART_BPS = 'd9600, //波特率9600
parameter CLK_FREQ = 'd50_000_000, //时钟频率50Mhz
parameter BYTES = 'd8, //需要发送数据的字节数
parameter S = 8'b0101_0011,
parameter U = 8'b0101_0101,
parameter C = 8'b0100_0011,
parameter E = 8'b0100_0101,
parameter EXCLAMATORY = 8'b0010_0001
)
(
input wire clk,
input wire rst_n,
input wire [(BYTES * 8 -1):0] pi_data,
input wire pi_flag,
output reg tx
);
localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS ;
//1S钟传输9600bit数据,时钟1S有5000000次,每传输1bi数据,共经过50000000/9600次时钟周期,
//故采样计数最大值50000000/9600=5208
reg work_en; //发送控制使能信号
reg [12:0] baud_cnt;//发送计数器,波特率9600,时钟频率50M,故计数5208次
reg bit_flag;//发送标志信号,baud_cnt为1时产生1个时钟周期的高电平
reg [(BYTES*8-1):0] UART_data; //需要发送的数据
reg [7:0] buffer_data; //发送数据缓存区,每次发送1字节
reg [12:0] cnt_num; //发送数据的字节数
reg byte_tx_done; //1字节数据发送完成标志信号
reg byte_tx_done_reg; //1字节数据发送完成标志信号打1拍,确保待发送数据给到发送数据缓存区
reg [4:0] bit_flag_cnt; //数据发送计数器,每发送1bit计数1次,发送完1字节后清零
reg pi_flag_reg1; //接收完成标志信号打一拍,将数据传递给buffer_data
reg pi_flag_reg2; //pi_flag_reg1打一拍,用于产生发送使能控制信号work_en
always @(posedge clk or negedge rst_n)
if (rst_n == 1’b0)
cnt_num <= 13’d0;
else if ((cnt_num == (BYTES-1)) && (byte_tx_done == 1’b1))
cnt_num <= 13’d0;
else if ((work_en == 1’b1) && (byte_tx_done == 1’b1))
cnt_num <= cnt_num + 1’d1;
always @(posedge clk or negedge rst_n)
if (rst_n == 1’b0)
bit_flag_cnt <= 5’b0;
else if (work_en == 1’b0)
bit_flag_cnt <= 5’b0;
else if( (bit_flag_cnt == 5’d9) && ( (bit_flag == 13’b1) && (work_en == 1’b1) ) )
bit_flag_cnt <= 5’d0;
else if((bit_flag == 1’b1) && (work_en == 1’b1))
bit_flag_cnt <= bit_flag_cnt + 1’b1;
always @(posedge clk or negedge rst_n)
if (rst_n == 1’b0)
byte_tx_done <= 1’b0;
else if ( (bit_flag_cnt == 5’d9) && ( (bit_flag == 13’b1) && (work_en == 1’b1) ) )
byte_tx_done <= 1’b1;
else
byte_tx_done <= 1’b0;
always @(posedge clk or negedge rst_n)
if (rst_n == 1’b0)
byte_tx_done_reg <= 1’b0;
else
byte_tx_done_reg <= byte_tx_done;
always @(posedge clk or negedge rst_n)
if (rst_n == 1’b0)
UART_data <= 'b0;
else if ((pi_flag == 1’b1)&&(cnt_num == 13’d0))
UART_data <= pi_data;
else if (byte_tx_done == 1’b1)
UART_data <= UART_data >> 8;
always @(posedge clk or negedge rst_n)
if( rst_n == 1’b0 )
pi_flag_reg1 <= 1’b0;
else if ((pi_flag == 1’b1) && (cnt_num == 13’d0) )
pi_flag_reg1 <= 1’b1;
else
pi_flag_reg1 <= 1’b0;
always @(posedge clk or negedge rst_n)
if( rst_n == 1’b0 )
pi_flag_reg2 <= 1’b0;
else if ((pi_flag_reg1 == 1’b1) && (cnt_num == 13’d0) )
pi_flag_reg2 <= 1’b1;
else
pi_flag_reg2 <= 1’b0;
always @(posedge clk or negedge rst_n)
if (rst_n == 1’b0)
buffer_data <= 8’b0;
else if ((pi_flag_reg1 == 1’b1)&&(cnt_num == 13’d0))
buffer_data <= UART_data[7:0];
else if ((bit_flag_cnt == 5’d0) && (byte_tx_done_reg == 1’b1))
buffer_data <= UART_data[7:0];
always @(posedge clk or negedge rst_n)
if(rst_n == 1’b0)
work_en <= 1’b0;
else if ((pi_flag_reg2 == 1’b1))
work_en <= 1’b1;
else if ((cnt_num == (BYTES-1)) && ((bit_flag_cnt == 5’d9) && (bit_flag == 1’b1)))
work_en <= 1’b0;
always @(posedge clk or negedge rst_n)
if(rst_n == 1’b0)
baud_cnt <= 13’b0;
else if ((work_en == 1’b0) || (baud_cnt == BAUD_CNT_MAX-1 ))
baud_cnt <= 13’b0;
else if(work_en == 1’b1)
baud_cnt <= baud_cnt +1’b1;
always @(posedge clk or negedge rst_n)
if(rst_n == 1’b0)
bit_flag <= 1’b0;
else if (baud_cnt == 13’b1)
bit_flag <= 1’b1;
else
bit_flag <= 1’b0;
always @(posedge clk or negedge rst_n)
if (rst_n == 1’b0)
tx <= 1’b1;
else if(bit_flag)
case (bit_flag_cnt)
0 : tx <= 1’b0;
1 : tx <= buffer_data[0];
2 : tx <= buffer_data[1];
3 : tx <= buffer_data[2];
4 : tx <= buffer_data[3];
5 : tx <= buffer_data[4];
6 : tx <= buffer_data[5];
7 : tx <= buffer_data[6];
8 : tx <= buffer_data[7];
9 : tx <= 1’b1;
default: tx <= 1’b1;
endcase
endmodule
3、仿真结果
4、上板实测
上位机成功接收到“SUCCESS!”文章来源:https://www.toymoban.com/news/detail-559754.html
文章来源地址https://www.toymoban.com/news/detail-559754.html
到了这里,关于基于FPGA实现串口多字节发送的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!