基于FPGA的任意字节数的串口发送(含源码工程)
文章目录
1、概述
2、串口发送驱动
3、任意字节发送的实现方法
4、仿真
4.1、单字节仿真
4.2、双字节仿真
4.3、5字节仿真
5、实测
5.1、单字节实测
5.2、双字节实测
5.3、5字节实测
1、概述
在这篇文章中串口(UART)的FPGA实现(含源码工程),实现了基于FPGA的串口发送驱动。利用发送驱动可以实现 起始位1bit+数据位8bit+停止位1bit 共10bit的单字节传输。
但是在实际应用过程中又经常需要一次性发送多个字节的数据。比如,一次发送一个位宽为【39:0】的数据。诚然,可以直接更改此文中的串口发送驱动,使其变成 起始位1bit+数据位40bit+停止位1bit 共42bit的多字节传输。这种方法理论上是可行的,因为UART协议并没有规定你一次要发送、接收多个少bit的数据,既然能发送8个bit,那同样能发送40个bit。
但是很不幸,实际上基本行不通,因为通用的绝大部分上位机都不支持一次解析40bit的数据位(如果你自己写上位机就当我没说)。
所以只能想点其他办法,比如:写个逻辑,多次调用8bit即单字节的串口发送驱动,40bit的数据就调用5次,也就是切割成5个 起始位1bit+数据位8bit+停止位1bit共10bit的单字节 分别发送过去就可以了。
2、串口发送驱动
请参考:串口(UART)的FPGA实现(含源码工程),在此文详细介绍了串口的发送驱动。
以下代码可以实现 1bit+数据位8bit+停止位1bit 共10bit的单字节传输,无奇偶校验。
// *******************************************************************************************************
// ** 作者 : 孤独的单刀
// ** 邮箱 : zachary_wu93@163.com
// ** 博客 : https://blog.csdn.net/wuzhikaidetb
// ** 日期 : 2022/07/31
// ** 功能 : 1、基于FPGA的串口发送驱动模块;
// 2、可设置波特率BPS、主时钟CLK_FRE;
// 3、起始位1bit,数据位8bit,停止位1bit,无奇偶校验;
// 4、每发送1个字节后拉高uart_tx_done一个周期,可用于后续发送多字节模块。
// ******************************************************************************************************* module uart_tx
#(parameter integer BPS = 9_600 , //发送波特率parameter integer CLK_FRE = 50_000_000 //主时钟频率
)
(
//系统接口input sys_clk , //系统时钟input sys_rst_n , //系统复位,低电平有效
//用户接口 input [7:0] uart_tx_data , //需要通过UART发送的数据,在uart_tx_en为高电平时有效input uart_tx_en , //发送有效,当其为高电平时,代表此时需要发送的数据有效
//UART发送 output reg uart_tx_done , //成功发送1BYTE数据后拉高一个周期output reg uart_txd //UART发送数据线tx
);//param define
localparam integer BPS_CNT = CLK_FRE / BPS; //根据波特率计算传输每个bit需要计数多个系统时钟
localparam integer BITS_NUM = 10 ; //发送格式确定需要发送的bit数,10bit = 1起始位 + 8数据位 + 1停止位//reg define
reg tx_state ; //发送标志信号,拉高代表发送过程正在进行
reg [7:0] uart_tx_data_reg ; //寄存要发送的数据
reg [31:0] clk_cnt ; //计数器,用于计数发送一个bit数据所需要的时钟数
reg [3:0] bit_cnt ; //bit计数器,标志当前发送了多少个bit//当发送使能信号到达时,寄存待发送的数据以免后续变化、丢失
always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)uart_tx_data_reg <=8'd0;else if(uart_tx_en) //要发送有效的数据uart_tx_data_reg <= uart_tx_data; //寄存需要发送的数据 else uart_tx_data_reg <= uart_tx_data_reg;
end //当发送使能信号到达时,进入发送过程
always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)tx_state <=1'b0; else if(uart_tx_en) tx_state <= 1'b1; //发送信号有效则进入发送过程//发送完了最后一个数据则退出发送过程 else if((bit_cnt == BITS_NUM - 1'b1) && (clk_cnt == BPS_CNT - 1'b1)) tx_state <= 1'b0; else tx_state <= tx_state;
end//发送数据完毕后拉高发送完毕信号一个周期,指示一个字节发送完毕
always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)uart_tx_done <=1'b0;//发送数据完毕后拉高发送完毕信号一个周期 else if((bit_cnt == BITS_NUM - 1'b1) && (clk_cnt == BPS_CNT - 1'b1)) uart_tx_done <=1'b1; else uart_tx_done <=1'b0;
end//进入发送过程后,启动时钟计数器与发送个数bit计数器
always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)beginclk_cnt <= 32'd0;bit_cnt <= 4'd0;endelse if(tx_state) begin //在发送状态if(clk_cnt < BPS_CNT - 1'd1)begin //一个bit数据没有发送完clk_cnt <= clk_cnt + 1'b1; //时钟计数器+1bit_cnt <= bit_cnt; //bit计数器不变end else begin //一个bit数据发送完了 clk_cnt <= 32'd0; //清空时钟计数器,重新开始计时bit_cnt <= bit_cnt+1'b1; //bit计数器+1,表示发送完了一个bit的数据end end else begin //不在发送状态clk_cnt <= 32'd0; //清零bit_cnt <= 4'd0; //清零end
end//根据发送数据计数器来给uart发送端口赋值
always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)uart_txd <= 1'b1; //默认为高状态,空闲状态else if(tx_state) //处于发送状态case(bit_cnt) //数据发送从低位到高位4'd0: uart_txd <= 1'b0; //起始位,拉低4'd1: uart_txd <= uart_tx_data_reg[0]; //发送最低位数据4'd2: uart_txd <= uart_tx_data_reg[1]; //4'd3: uart_txd <= uart_tx_data_reg[2]; //4'd4: uart_txd <= uart_tx_data_reg[3]; //4'd5: uart_txd <= uart_tx_data_reg[4]; //4'd6: uart_txd <= uart_tx_data_reg[5]; //4'd7: uart_txd <= uart_tx_data_reg[6]; //4'd8: uart_txd <= uart_tx_data_reg[7]; //发送最高位数据4'd9: uart_txd <= 1'b1; //终止位,拉高default:uart_txd <= 1'b1; endcase else //不处于发送状态uart_txd <= 1'b1; //默认为高状态,空闲状态
endendmodule
3、任意字节发送的实现方法
串口发送驱动模块的对外端口如下:
其中uart_tx_done信号是关键。当一个字节的数据被按约定的串口协议发送出去后,该信号就会拉高一个时钟周期,表示一次传输结束。
可以在发送完一个字节后,将该信号作为发送下一个字节的使能信号,直到所有的字节都被发送完毕。
但是有一个需要注意的问题:第一个字节的发送使能是无法参考信号 uart_tx_done,那么第一个信号何时发送?同样的,在任意字节发送模块设计一个对外信号:uart_bytes_en,只有当该信号有效时才发起一次传输,同时该信号还可以作为第一个字节的发送使能信号,如下:
总结一下,多字节的发送逻辑:
- 1、用户传递多字节发送使能+多字节数据
- 2、根据多字节发送使能发送最低字节(最低8bit),作为第一次发送的单字节
- 3、根据单字节发送完毕指示信号,开始发送第二个单字节,即多字节的次低byte
- 4、所有单字节均被发送完毕后,拉高uart_bytes_done,表示一次多字节发送结束
完整代码如下:
// *******************************************************************************************************************
// ** 作者 : 孤独的单刀
// ** 邮箱 : zachary_wu93@163.com
// ** 博客 : https://blog.csdn.net/wuzhikaidetb
// ** 日期 : 2022/07/31
// ** 功能 : 1、基于FPGA的串口多字节发送模块;
// 2、可设置一次发送的字节数、波特率BPS、主时钟CLK_FRE;
// 3、UART协议设置为起始位1bit,数据位8bit,停止位1bit,无奇偶校验(不可在端口更改,只能更改发送驱动源码);
// 4、每发送1次多字节后拉高指示信号一个周期,指示一次多字节发送结束;
// 5、数据发送顺序,先发送低字节、再发送高字节。如:发送16’h12_34,先发送单字节8'h34,再发送单字节8'h12。
// ******************************************************************************************************************* module uart_bytes_tx
#(parameter integer BYTES = 4 , //发送字节数,单字节8bitparameter integer BPS = 9_600 , //发送波特率parameter integer CLK_FRE = 50_000_000 //输入时钟频率
)
(
//系统接口input sys_clk , //系统时钟input sys_rst_n , //系统复位,低电平有效
//用户接口 input [(BYTES * 8 - 1):0] uart_bytes_data , //需要通过UART发送的多字节数据,在uart_bytes_en为高电平时有效input uart_bytes_en , //发送有效,当其为高电平时,代表此时需要发送的数据有效
//UART发送 output uart_bytes_done , //成功发送完所有字节数据后拉高1个时钟周期output uart_txd //UART发送数据线tx
);//reg define
reg [(BYTES*8-1):0] uart_bytes_data_reg; //寄存接收到的多字节数据
reg work_en; //高电平表示处于发送状态,低电平表示空闲状态
reg [9:0] byte_cnt; //发送的字节个数计数(因为懒直接用10bit计数,最大可以表示1024BYTE,大概率不会溢出)
reg [7:0] uart_sing_data; //拆解的要发送的单个字节数据
reg uart_sing_en; //要发送的单个字节数据发送使能
reg uart_bytes_done_reg; //所有字节发送完毕打拍
reg uart_sing_done_reg; //单个字节数据发送完毕打拍//wire define
wire uart_sing_done; //单个字节发送完成标志信号//对端口赋值
assign uart_bytes_done = uart_bytes_done_reg;//当发送使能信号到达时,寄存待发送的多字节数据以免后续变化、丢失
always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)uart_bytes_data_reg <= 0;else if(uart_bytes_en && ~work_en) //要发送有效的数据,且并未处于发送状态uart_bytes_data_reg <= uart_bytes_data; //寄存需要发送的数据 else if(uart_sing_done) uart_bytes_data_reg <= uart_bytes_data_reg >> 8; //发送完一个数据后,把多字节数据右移8bitelse uart_bytes_data_reg <= uart_bytes_data_reg;
end //当发送使能信号到达时,进入工作状态
always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)work_en <= 1'b0;else if(uart_bytes_en && ~work_en) //要发送有效的数据且未处于工作状态work_en <= 1'b1; //进入发送状态 else if(uart_sing_done && byte_cnt == BYTES - 1) //发送完了最后一个字节的数据work_en <= 1'b0; //发送完毕,退出工作状态 else work_en <= work_en;
end //在工作状态对发送的数据个数进行计数
always @(posedge sys_clk or negedge sys_rst_n)begin if(!sys_rst_n) byte_cnt <= 0; else if(work_en)begin //处于发送状态则需要对发送的字节个数计数if(uart_sing_done && byte_cnt == BYTES - 1) //计数到了最大值则清零byte_cnt <= 0; else if(uart_sing_done) //发送完一个单字节则计数器+1byte_cnt <= byte_cnt + 1'b1; else byte_cnt <= byte_cnt; end else //不处于发送状态则清零byte_cnt <= 0;
end//打拍凑时序·~·
always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)uart_sing_done_reg <= 0;else uart_sing_done_reg <= uart_sing_done;
end//发送单个字节的数据
always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)uart_sing_data <= 8'd0;else if(uart_bytes_en && ~work_en) //进入工作状态后马上发送第一个数据uart_sing_data <= uart_bytes_data[7:0]; //发送最低字节else if(uart_sing_done_reg) //发送完一个字节则发送另一个字节uart_sing_data <= uart_bytes_data_reg[7:0]; //先右移8bit,然后取低8bitelseuart_sing_data <= uart_sing_data; //保持稳定
end//发送单个字节的数据使能
always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)uart_sing_en <= 1'b0;else if(uart_bytes_en && ~work_en) //进入工作状态后马上发送第一个数据uart_sing_en <= 1'b1; else if(uart_sing_done_reg && work_en) //发送完一个字节则发送另一个字节uart_sing_en <= 1'b1; else uart_sing_en <= 1'b0; //其他时候则为0
end//所有数据发送完毕
always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)uart_bytes_done_reg <= 1'b0;else if(uart_sing_done && byte_cnt == BYTES - 1)uart_bytes_done_reg <= 1'b1;else uart_bytes_done_reg <= 1'b0;
end//例化发送驱动模块
uart_tx #(.BPS (BPS ), .CLK_FRE (CLK_FRE )
)
uart_tx_inst( .sys_clk (sys_clk ), .sys_rst_n (sys_rst_n ),.uart_tx_data (uart_sing_data ), .uart_tx_en (uart_sing_en ),.uart_tx_done (uart_sing_done ),.uart_txd (uart_txd )
);endmodule
4、仿真
使用该模块发送数据3次,观测发送结果是否符合UART协议要求。分别使用单字节(8位)、双字节(16位)、5字节(40位)进行测试。
4.1、单字节仿真
TB如下:
`timescale 1ns/1ns //定义时间刻度module tb_uart_bytes_tx();localparam integer BYTES = 1 ; //一次发送的字节个数localparam integer BPS = 230400 ; //波特率
localparam integer CLK_FRE = 50_000_000 ; //系统频率50Mreg sys_clk ; //系统时钟
reg sys_rst_n ; //系统复位,低电平有效
reg [(BYTES * 8 - 1):0] uart_bytes_data ; //需要通过UART发送的多字节数据,在uart_bytes_en为高电平时有效
reg uart_bytes_en ; //发送有效,当其为高电平时,代表此时需要发送的数据有效
wire uart_bytes_done ; //成功发送完所有BYTE数据后拉高1个时钟周期
wire uart_txd ; //UART发送数据线initial begin sys_clk <=1'b0; sys_rst_n <=1'b0;uart_bytes_en <=1'b0;uart_bytes_data <= 0;#80 //系统开始工作sys_rst_n <=1'b1;
//*******************************************************************************
//第1次发送随机数据#90 //发送1次随机的多字节数据uart_bytes_en <=1'b1; uart_bytes_data <= {$random}; //生成随机数据#20 uart_bytes_en <=1'b0; wait(uart_bytes_done); //等待其发送完
//*******************************************************************************
//*******************************************************************************
//第2次发送随机数据#20 uart_bytes_en <=1'b1; uart_bytes_data <= {$random}; //发送1次随机的多字节数据#20 uart_bytes_en <=1'b0; wait(uart_bytes_done); //等待其发送完
//*******************************************************************************
//第3次发送随机数据 #20 uart_bytes_en <=1'b1; uart_bytes_data <= {$random}; //发送1次随机的多字节数据#20 uart_bytes_en <=1'b0; wait(uart_bytes_done); //等待其发送完
//******************************************************************************* #1000 $finish(); //结束仿真
endalways #10 sys_clk=~sys_clk; //设置主时钟,20ns,50M//例化多字节发送模块
uart_bytes_tx #(.BYTES (BYTES ),.BPS (BPS ), .CLK_FRE (CLK_FRE )
)
uart_bytes_tx_inst( .sys_clk (sys_clk ), .sys_rst_n (sys_rst_n ),.uart_bytes_data (uart_bytes_data ), .uart_bytes_en (uart_bytes_en ),.uart_bytes_done (uart_bytes_done ),.uart_txd (uart_txd )
);
endmodule
仿真结果如下:
- 该模块调用了3次,分别发送数据8'h24,8'h81,8'h09
- 串口发送驱动发送了同样的3个数据8'h24,8'h81,8'h09
- 以第一次发送8'h24为例,此时串口发送线TX上的数据分别为0(起始位) --0--0--1--0--0--1--0--0--1(停止位),根据数据低位在前,高位在后的原则,即8'b00100100,也就是8'h24
4.2、双字节仿真
TB基本不用修改,仅仅把BYTES这个参数改成2就行。仿真结果如下:
- 该模块调用了3次,分别发送数据16'h3524,16'h5e81,16'hd609
- 串口发送驱动发送了6个数据8'h24,8'h35,8'h81,8'h5e,8'h09,8'hd6
- 根据先发低字节后发高字节的原则,将3个双字节拆成了6个单字节分别发送
4.3、5字节仿真
TB基本不用修改,仅仅把BYTES这个参数改成5就行。仿真结果如下:
您照着上面的逻辑看看就行,我就不啰嗦了。
5、实测
下板实测的话,需要写个顶层模块来例化这个任意字节的串口发送模块。在顶层模块,设置成每1s拉高一次发送信号,同时将要发送的数据+1。
5.1、单字节实测
顶层模块如下:
// *******************************************************************************************************************
// ** 作者 : 孤独的单刀
// ** 邮箱 : zachary_wu93@163.com
// ** 博客 : https://blog.csdn.net/wuzhikaidetb
// ** 日期 : 2022/07/31
// ** 功能 : 1、对基于FPGA的串口多字节发送模块进行测试的模块;
// 2、设置好一次发送的字节数、波特率、主时钟频率;
// 3、UART协议设置为起始位1bit,数据位8bit,停止位1bit,无奇偶校验(不可在端口更改,只能更改发送驱动源码);
// 4、数据发送顺序,先发送低字节、再发送高字节。如:发送16’h12_34,先发送单字节8'h34,再发送单字节8'h12。
// ******************************************************************************************************************* module uart_bytes_tx_test(
//系统接口input sys_clk , //主时钟input sys_rst_n , //低电平有效的复位信号
//UART发送线 output uart_txd //UART发送线
);localparam integer BYTES = 1 ; //发送的字节数,单字节8bit
localparam integer BPS = 115200 ; //发送波特率
localparam integer CLK_FRE = 50_000_000 ; //输入时钟频率
localparam integer CNT_MAX = 50_000_000 ; //发送时间间隔,1秒reg [31:0] cnt_time;
reg uart_bytes_en; //发送使能,当其为高电平时,代表此时需要发送数据
reg [BYTES*8-1 :0] uart_bytes_data; //需要通过UART发送的数据,在uart_bytes_en为高电平时有效//1s计数模块,每隔1s发送一个数据和拉高发送使能信号一次,数据从初始值开始递增1
always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)begincnt_time <= 'd0;uart_bytes_en <= 1'd0;uart_bytes_data <= 'h12; //初始数据endelse if(cnt_time == (CNT_MAX - 1'b1))begincnt_time <= 'd0;uart_bytes_en <= 1'd1; //拉高发送使能uart_bytes_data <= uart_bytes_data + 1'd1; //发送数据累加1endelse begincnt_time <= cnt_time + 1'd1;uart_bytes_en <= 1'd0;uart_bytes_data <= uart_bytes_data; end
end//例化串口多字节发送模块
uart_bytes_tx
#(.BYTES (BYTES ), .BPS (BPS ), .CLK_FRE (CLK_FRE )
)
uart_bytes_tx_inst
( .sys_clk (sys_clk ), .sys_rst_n (sys_rst_n ), .uart_bytes_data (uart_bytes_data ), .uart_bytes_en (uart_bytes_en ), .uart_bytes_done ( ), .uart_txd (uart_txd )
);endmodule
初始值设定为8'h13,这样上位机每1s就可以接收一个数据,其值分别为8'h13、8'h14、8'h15、8'h16、8'h17·····,上位机接收到的数据如下:
测试结果与预期一致。
5.2、双字节实测
顶层模块如下:
// *******************************************************************************************************************
// ** 作者 : 孤独的单刀
// ** 邮箱 : zachary_wu93@163.com
// ** 博客 : https://blog.csdn.net/wuzhikaidetb
// ** 日期 : 2022/07/31
// ** 功能 : 1、对基于FPGA的串口多字节发送模块进行测试的模块;
// 2、设置好一次发送的字节数、波特率、主时钟频率;
// 3、UART协议设置为起始位1bit,数据位8bit,停止位1bit,无奇偶校验(不可在端口更改,只能更改发送驱动源码);
// 4、数据发送顺序,先发送低字节、再发送高字节。如:发送16’h12_34,先发送单字节8'h34,再发送单字节8'h12。
// ******************************************************************************************************************* module uart_bytes_tx_test(
//系统接口input sys_clk , //主时钟input sys_rst_n , //低电平有效的复位信号
//UART发送线 output uart_txd //UART发送线
);localparam integer BYTES = 2 ; //发送的字节数,单字节8bit
localparam integer BPS = 115200 ; //发送波特率
localparam integer CLK_FRE = 50_000_000 ; //输入时钟频率
localparam integer CNT_MAX = 50_000_000 ; //发送时间间隔,1秒reg [31:0] cnt_time;
reg uart_bytes_en; //发送使能,当其为高电平时,代表此时需要发送数据
reg [BYTES*8-1 :0] uart_bytes_data; //需要通过UART发送的数据,在uart_bytes_en为高电平时有效//1s计数模块,每隔1s发送一个数据和拉高发送使能信号一次,数据从初始值开始递增1
always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)begincnt_time <= 'd0;uart_bytes_en <= 1'd0;uart_bytes_data <= 'h3412; //初始数据endelse if(cnt_time == (CNT_MAX - 1'b1))begincnt_time <= 'd0;uart_bytes_en <= 1'd1; //拉高发送使能uart_bytes_data <= uart_bytes_data + 1'd1; //发送数据累加1endelse begincnt_time <= cnt_time + 1'd1;uart_bytes_en <= 1'd0;uart_bytes_data <= uart_bytes_data; end
end//例化串口多字节发送模块
uart_bytes_tx
#(.BYTES (BYTES ), .BPS (BPS ), .CLK_FRE (CLK_FRE )
)
uart_bytes_tx_inst
( .sys_clk (sys_clk ), .sys_rst_n (sys_rst_n ), .uart_bytes_data (uart_bytes_data ), .uart_bytes_en (uart_bytes_en ), .uart_bytes_done ( ), .uart_txd (uart_txd )
);endmodule
初始值设定为16'h3413,这样上位机每1s就可以接收一个数据,其值分别为8'h13、8'h34、8'h14、8'h34、8'h15、8'h34·····,上位机接收到的数据如下:
测试结果与预期一致。
5.3、5字节实测
顶层模块如下:
// *******************************************************************************************************************
// ** 作者 : 孤独的单刀
// ** 邮箱 : zachary_wu93@163.com
// ** 博客 : https://blog.csdn.net/wuzhikaidetb
// ** 日期 : 2022/07/31
// ** 功能 : 1、对基于FPGA的串口多字节发送模块进行测试的模块;
// 2、设置好一次发送的字节数、波特率、主时钟频率;
// 3、UART协议设置为起始位1bit,数据位8bit,停止位1bit,无奇偶校验(不可在端口更改,只能更改发送驱动源码);
// 4、数据发送顺序,先发送低字节、再发送高字节。如:发送16’h12_34,先发送单字节8'h34,再发送单字节8'h12。
// ******************************************************************************************************************* module uart_bytes_tx_test(
//系统接口input sys_clk , //主时钟input sys_rst_n , //低电平有效的复位信号
//UART发送线 output uart_txd //UART发送线
);localparam integer BYTES = 5 ; //发送的字节数,单字节8bit
localparam integer BPS = 115200 ; //发送波特率
localparam integer CLK_FRE = 50_000_000 ; //输入时钟频率
localparam integer CNT_MAX = 50_000_000 ; //发送时间间隔,1秒reg [31:0] cnt_time;
reg uart_bytes_en; //发送使能,当其为高电平时,代表此时需要发送数据
reg [BYTES*8-1 :0] uart_bytes_data; //需要通过UART发送的数据,在uart_bytes_en为高电平时有效//1s计数模块,每隔1s发送一个数据和拉高发送使能信号一次,数据从初始值开始递增1
always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)begincnt_time <= 'd0;uart_bytes_en <= 1'd0;uart_bytes_data <= 40'h9a_78_56_34_12; //初始数据endelse if(cnt_time == (CNT_MAX - 1'b1))begincnt_time <= 'd0;uart_bytes_en <= 1'd1; //拉高发送使能uart_bytes_data <= uart_bytes_data + 1'd1; //发送数据累加1endelse begincnt_time <= cnt_time + 1'd1;uart_bytes_en <= 1'd0;uart_bytes_data <= uart_bytes_data; end
end//例化串口多字节发送模块
uart_bytes_tx
#(.BYTES (BYTES ), .BPS (BPS ), .CLK_FRE (CLK_FRE )
)
uart_bytes_tx_inst
( .sys_clk (sys_clk ), .sys_rst_n (sys_rst_n ), .uart_bytes_data (uart_bytes_data ), .uart_bytes_en (uart_bytes_en ), .uart_bytes_done ( ), .uart_txd (uart_txd )
);endmodule
初始值设定为40'h9a78563413,这样上位机每1s就可以接收一个数据,其值分别为8'h13、8'h34、8'h56、8'h78、8'h9a、8'h14、8'h34、8'h56、8'h78、8'h9a、·····,上位机接收到的数据如下:
测试结果与预期一致。
工程源码点这里下载(提取码:nk20)
-
基于FPGA的任意字节数的串口发送(含源码工程)相关推荐
- 【014】基于Vue.js的移动端购物商城网站(含源码、课设报告)
文章目录 一.项目介绍 二.代码及报告获取 一.项目介绍 基于Vue.js的移动端购物商城网站(含源码.课设报告),代码获取放在文末了,码字不易,感谢点赞~ 一.系统概述 本部分主要是对项目进行简要描 ...
- 基于深度学习的恶意样本行为检测(含源码) ----采用CNN深度学习算法对Cuckoo沙箱的动态行为日志进行检测和分类...
from:http://www.freebuf.com/articles/system/182566.html 0×01 前言 目前的恶意样本检测方法可以分为两大类:静态检测和动态检测.静态检测是指并 ...
- 基于51单片机霍尔测速直流电机控制设计(含源码+原理图+论文+PCB封装)、基于STM32闭环步进电机控制系统设计(仿真,程序,说明)-转发分享
设计思路: 本文主要研究了利用MCS-51系列单片机控制PWM信号从而实现对直流电机转速进行控制的方法.本文中采用了三极管组成了PWM信号的驱动系统,并且对PWM信号的原理.产生方法以及如何通过软件编 ...
- 8.图片组件和动画效果--从零起步实现基于Html5的WEB设计器Jquery插件(含源码)...
前面示例我建立了三种形状的组件,圆.矩形.椭圆,本节我将再扩展两种类型:图片和动画,并通过这个过程来论证前面OOP的编程是如何简化扩展工作的: 首先要在工具条里增加这两个组件,以便可以拖动: < ...
- 7.组件连线(贝塞尔曲线)--从零起步实现基于Html5的WEB设计器Jquery插件(含源码)...
上节讲到如何创建组件,清除设计器视图,以及设计视图的持久化和恢复,本节将重点讲如何实现组件间的连线,前面章节有提到为了方便从持久化文件中恢复,组件和连线是分别存放的:nodes和lines对象,两个组 ...
- 基于HTML实现的电商团购网站(含源码)
源码下载地址在文章末尾! 网站截图 细节演示 网页中使用了很多的鼠标交互效果,例如轮播和鼠标悬停特效 左侧广告弹窗跟随效果: 右侧导航栏的显示与隐藏效果: 源码下载地址 https://downloa ...
- 27.串口通信实验源码讲解
串口通信实验源码讲解 笔记基于正点原子官方视频 视频连接https://www.bilibili.com/video/BV1Wx411d7wT?p=71&spm_id_from=333.100 ...
- java毕业设计——基于java+EVENODD编码的基于纠错码的冗余技术设计与实现(毕业论文+程序源码)——基于纠错码的冗余技术
基于java+EVENODD编码的基于纠错码的冗余技术设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+EVENODD编码的基于纠错码的冗余技术设计与实现,文章末尾附有本毕业设计的 ...
- STM32 USART串口DMA 接收和发送的源码详解!
硬件平台:STM32F103ZET6: 开发环境:KEIL 4: 先说说应用通讯模式,串口终端的工作方式和迪文屏差不多,终端被动接受MCU发的指令,终端会偶尔主动发送一些数据给MCU(像迪文屏的触摸信 ...
- 基于Java毕业设计校园社团管理平台演示录像2021源码+系统+mysql+lw文档+部署软件
基于Java毕业设计校园社团管理平台演示录像2021源码+系统+mysql+lw文档+部署软件 基于Java毕业设计校园社团管理平台演示录像2021源码+系统+mysql+lw文档+部署软件 本源码技 ...
最新文章
- ZTE-中兴捧月-北京线下测试赛--B题
- JavaScript之浅复制【拷贝】与深复制【拷贝】【二】
- Android源码分析(三):Mms模块总结(一)
- java jsp 原理_jsp的工作原理是什么
- ThinkPHP笔记——配置分组产生无法加载Index错误解决办法
- 高性能对象存储MinIO学习
- Web测试中容易被忽略的Charset问题
- Solr基础教程之solrconfig.xml(三)
- Linux:查看磁盘空间占用情况
- Java通过JNI/JNA加载dll库文件调用C接口,出现“java.lang.UnsatisfiedLinkError: no XXX in java.library.path”问题
- listview控件在php的使用方法,VBA窗体之ListView控件的基本应用 | VBA实例教程
- java 项目开发日报_CSDN日报191114:Java开发干货分享
- hutool实战(带你掌握里面的各种工具)目录
- 家庭水族馆,智能加热棒解决方案
- 数据库的主从复制原理(超级详细)
- lrzsz的交叉编译与使用
- zkSnarks:QAP上构造零知识证明
- 葡萄酒数据集_如何使用数据科学来理解什么使葡萄酒味道更好
- kdj值应用口诀_KDJ应用口诀,一文教你巧妙利用KDJ买卖股票
- java jdk17 Tomcat
热门文章
- java深克隆 浅克隆_通过Java中深克隆与浅克隆来理解克隆
- mac系统通过ADB与scrcpy实现手机投屏
- 三星s8怎么分屏操作_一心三用 三星Galaxy Z Fold2 5G成多任务处理大师
- 抄送列表 ,处理邮件,年会抽奖
- forward和redirect的区别是什么?
- windows虚拟机共享windows主机文件
- android iphone 记事本,苹果手机上有简单实用的便签记事本app吗?
- 如何学好高中数学 提高高中数学成绩秒杀技巧(这几点很重要)
- 城里人看呆!没想到现在景区都这么会玩了
- 计算机防火墙服务不能启动不了,Windows防火墙不能启动 服务也不能启动,怎么回事?...
- 【014】基于Vue.js的移动端购物商城网站(含源码、课设报告)