FPGA串口/UART单字节发送程序

最近一周因为疫情封控在家,整个人都快废了,天天躺。更新一下串口发送,串口单字节发送程序和串口单字节接收程序的区别不大,而且可以说更简单,因为接收的时候需要考虑传输线上的每个bit位在什么时间点采样,而发送不需要考虑。由于区别不大,就不做过多阐述了。在看完我上篇串口接收程序文章以及程序注释,再来看串口发送,思路就很清晰。其关键就是在发送每个bit位的过程中,把待发送字节的对应bit位赋值给tx线就行。程序注释没有串口接收程序的注释详细。

以下是手敲的代码,已经验证。

module uart_tx
#(parameter CLK_FRE=50_000_000,//系统频率
parameter BPS=115200//串口波特率
)
(
	input sys_clk,
	input sys_rst_n,
	input [7:0] databyte,//待发送的字节
	input tx_en,//发送使能信号,为高电平就启动发送
	
	output reg tx,//串口发送线
	output reg tx_done//发送完成信号
);
localparam CNT_MAX = CLK_FRE/BPS;//发送一个bit的计数值,计算过程参考串口接收程序注释

reg [29:0] cnt_clk;//对系统时钟进行计数
reg [3:0] bit_cnt;//对发送bit位进行计数

reg tx_state;//发送状态,为1正在发送,为0不在发送状态

//发送使能信号tx_en为高,就让发送状态为1,表示处于发送状态,在发送完成后清零
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)
		tx_state <= 1'b0;
	else if(tx_en)
		tx_state <= 1'b1;
	else if(tx_done)
		tx_state <= 1'b0;
	else
		tx_state <= tx_state;
end

//tx_state为1时,就启动cnt_clk,每当计数到CNT_MAX - 1时就清零,重新开始计数。tx_state为0时,cnt_clk不计数。
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)
		cnt_clk <= 30'd0;
	else if(tx_state)begin
		if(cnt_clk == (CNT_MAX - 1))
			cnt_clk <= 30'd0;
		else
			cnt_clk <= cnt_clk + 1'b1;
	end
	else
		cnt_clk <= 30'd0;
end

//bit_cnt对已经发送bit位进行计数,每当bit_cnt等于9时就清零,0-9共十位表示一次发送完成。
//每当cnt_clk等于CNT_MAX - 1时,bit_cnt就加1
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)
		bit_cnt <= 4'd0;
	else if(bit_cnt == 9)
		bit_cnt <= 4'd0;
	else if(cnt_clk == (CNT_MAX - 1))
		bit_cnt <= bit_cnt + 1'b1;
	else
		bit_cnt <= bit_cnt;
end

//bit_cnt等于9时,一次发送完成,拉高tx_done,仅持续一个系统时钟周期
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)
		tx_done <= 1'b0;
	else if(bit_cnt == 9)
		tx_done <= 1'b1;
	else
		tx_done <= 1'b0;
end

//根据bit_cnt的值,给tx赋值,比如bit_cnt=0,就是发送起始位0
//tx初始值赋值为1,因为串口空闲态为1
//bit_cnt如果产生其他意外值,tx就赋值为1,一般不会出现这种情况但是default情况下如果没有赋值tx的话,会产生警告,有latch
always@(*)begin
	if(!sys_rst_n)
		tx = 1'b1;
	else if(tx_state)begin
		case(bit_cnt)
			0:tx = 1'b0;
			1:tx = databyte[0];
			2:tx = databyte[1];
			3:tx = databyte[2];
			4:tx = databyte[3];
			5:tx = databyte[4];
			6:tx = databyte[5];
			7:tx = databyte[6];
			8:tx = databyte[7];
			9:tx = 1'b1;
			default:tx = 1'b1;
		endcase
	end
	else
		tx <= 1'b1;
end

endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值