基于FPGA实现串口多字节发送

   在串口试验中,不管是野火还是正点原子的例程,都是单字节的回环测试,无法进行多字节的发送,在野火的串口程序基础上,进行了修改,实现串口多字节的发送。

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!”

在这里插入图片描述

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值