小梅哥FPGA学习笔记——串口发送模块

串口发送模块结构框图

发送模块具体实现结构框图如图所示,按照图片的内容一步步实现发送模块的设计。
在这里插入图片描述
DR_LUT查找表的作用是选择不同波特率时,得到对应波特率的计数时间。然后将计数时间的装载值给到Div_Cnt模块,目的是通过改变装载值,来改变波特率的计数时间,以实现不同波特率之间的切换。
Div_cnt是一个计数器,用来产生bps_clk信号,也就是串口的波特率时钟信号。再将波特率时钟信号给到bps_cnt中。bps_cnt的作用是产生一个以波特率时钟为基础的计数器。这样就可以计数波特率时钟下的每一位数据。如果得到计数完成信号(Tx_done)计数器进行清零。
计数完成信号由比较器产生,当计数器满11位次时,得到波特率下的十一个数据,这时产生完成信号。
通过波特率计数器(bps_cnt),计数值从0-10循环,不同计数值作为十选一多路器的控制端,选择不同的数据进行输出,从而实现输出串口数据。
下面的send_en始能信号作用是:当始能开始时才发送数据,并且发送一次成功以后由Tx_done信号控制停止发送。通过两个二选一多路器来实现。如果始能按下,这时控制计数器开始工作输出发送信号,在这个过程中如果发送完成信号产生,就停止发送。
参考代码如下

module uart_byte_tx(
	Clk,
	Rst_n,
	data_byte,
	send_en,
	baud_set,
	
	rs232_tx,
	tx_done,
	uart_state
);

	input Clk;
	input Rst_n;
	input [7:0]data_byte;
	input send_en;
	input [2:0]baud_set;
	
	output reg rs232_tx;
	output reg tx_done;
	output reg uart_state;

	
	reg bps_clk;//波特率时钟
	
	reg [15:0]div_cnt;//分频计数器
	
	reg [15:0]bps_dr;//分频计数最大值
	
	reg [3:0]bps_cnt;//波特率时钟计数器
	
	reg [7:0]r_data_byte;//不直接取data_byte的值,通过r_data_byte寄存器进行寄存,防止直接取data_byte时候,数据改变导致错误。
	
	localparam start_bit = 1'b0;
	localparam stop_bit = 1'b1;
	
	//使能控制信号部分,两个二选一多路器,有优先级。
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		uart_state <= 1'b0;
	else if(send_en)
		uart_state <= 1'b1;
	else if(tx_done)
		uart_state <= 1'b0;
	else 
		uart_state <= uart_state;
	
	
	//只在en有效的时候,才将寄存器数据进行更新。
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		r_data_byte <= 8'd0;
	else if(send_en)
		r_data_byte <= data_byte;
	else
		r_data_byte <= r_data_byte;
	
	//dr_lut 查找表设计通常使用case语句实现
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		bps_dr <= 16'd5207;
	else begin
		case(baud_set)
			0:bps_dr <= 16'd5207;//9600
			1:bps_dr <= 16'd2603;//19200
			2:bps_dr <= 16'd1301;//38400
			3:bps_dr <= 16'd867; //57600
			4:bps_dr <= 16'd433; //115200
			default : bps_dr <= 16'd5207;	
		endcase
	end
	
	
	
	//div_counter
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		div_cnt <= 16'd0;
	else if(uart_state) begin
		if(div_cnt == bps_dr)
			div_cnt <= 0; 
	else
			div_cnt <= div_cnt +1'b1;
	end	
	else 
		div_cnt <= 16'd0;
		
		
		
	//bps_clk generate
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		bps_clk <= 1'b0;
	else if(div_cnt == 16'd1)
		bps_clk <= 1'b1;
	else
		bps_clk <= 1'b0;
		
		
	//bps_cnt
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		bps_cnt <= 4'd0;
	else if(tx_done)
		bps_cnt <= 4'd0;
	else if(bps_clk)
		bps_cnt <= bps_cnt + 1'b1;
	else
		bps_cnt <= bps_cnt; 
		
	//bps_cnt信号和11的比较器,产生发送完成信号	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		tx_done <= 1'b0;
	else if(bps_cnt == 4'd11)
		tx_done <= 1'b1;
	else
		tx_done <= 1'b0;
		
	//十选一多路器
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		rs232_tx <= 1'b1;
	else begin
		case (bps_cnt)
			0:rs232_tx <= 1'b1;
			1:rs232_tx <= start_bit;
			2:rs232_tx <= r_data_byte[0];
			3:rs232_tx <= r_data_byte[1];
			4:rs232_tx <= r_data_byte[2];
			5:rs232_tx <= r_data_byte[3];
			6:rs232_tx <= r_data_byte[4];
			7:rs232_tx <= r_data_byte[5];
			8:rs232_tx <= r_data_byte[6];
			9:rs232_tx <= r_data_byte[7];
			10:rs232_tx <= stop_bit;
			default:rs232_tx <= 1'b1;
		endcase
	end
	
	
		
endmodule

顶层模块

为了实现串口发送模块功能,需要调用写好的串口发送模块来进行测试。在工程中添加之前写好的按键模块。将按键模块中的按键状态,通过assign赋值语句连接到串口发送模块的始能信号(send_en)上。
添加issp模块给测试数据,将data连接到data上。给好指定波特率。并且将串口状态信号连接到led上,这样每次信号发送完成,状态指示灯会亮一下,提示程序是否正常运行。
参考代码

module uart_tx_top(Clk,Rst_n,rs232_tx,key_in0,led);
	input Clk;
	input Rst_n;
	input key_in0;

	output rs232_tx;
	output led;
	
	
	wire send_en;
	wire [7:0]data_byte;
	wire key_flag0;
	wire key_state0;
	
	
	assign send_en = key_flag0 & !key_state0;
	
	
		uart_byte_tx uart_byte_tx_0(
		.Clk			(Clk),
		.Rst_n		(Rst_n),
		.data_byte	(data_byte),
		.send_en		(send_en),
		.baud_set	(3'd4),
		
		.rs232_tx	(rs232_tx),
		.tx_done		(),
		.uart_state	(led)
	);
	
		key_filter key_filter_0(
	.Clk          (Clk),
	.Rst_n        (Rst_n),
	.key_in       (key_in0),
	.key_flag     (key_flag0),
	.key_state    (key_state0)
	);
	
	issp issp_0(
	.probe  (),
	.source (data_byte)
	);
	

	
endmodule
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泡泡糖呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值