Verilog RTL 代码实战 07——RS232串口发送模块

1.时序

发送模块的功能在于:对输入的一个多位数据,按照波特率规定的时间拆分成一位一位的数据发送
在这里插入图片描述

①tx模块多了一个触发信号,也就是rx模块的rx_over作为tx模块的trig信号

②同样是tx的第一个下降沿来之后,开始发送;发送完成后拉高,结束传输

③传输的速率看波特率,根据波特率计算每个数据发送所需要的时间

2.分析

①同样使用两个计数器,分别计数一个bit的时间和bit的个数

②使用一个寄存器存下输入进来的发送数据

③标志flag_tx的有效区域

④tx的发送使用一个case语句完成,且在flag_tx下完成,初值为1

⑤大致模块:
在这里插入图片描述

3.verilog代码

module tx
(
	input		clk,
	input		rst_n,
	input [7:0]	tx_data,
	input		trig,
	output reg	tx
);

//参数
parameter		_9600 	= 	5208;
parameter		_8bit	=	9;
//内部信
reg [7:0]		reg_tx_data;
reg			flag_tx;
reg [12:0]		cnt_9600;
reg [3:0]		cnt_8bit;

//将输入数据存入寄存器
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		reg_tx_data <= 0;
	else if(trig && !flag_tx)
		reg_tx_data <= tx_data;
		
end
//传输有效区域信号
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		flag_tx <= 0;
	else if(trig && !flag_tx)
		flag_tx <= 1;
	else if(flag_tx && cnt_8bit == _8bit-1 && cnt_9600 == _9600-1)
		flag_tx <=0;
end
//一位数据传输时间计数
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		cnt_9600 <= 0;
	else if(flag_tx)begin
	     if(cnt_9600 == _9600-1)
		cnt_9600 <= 0;
	     else
		cnt_9600 <= cnt_9600 + 1;
	end
	
end
//数据个数计数
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		cnt_8bit <= 0;
	else if(flag_tx && cnt_9600 == _9600-1)begin
		if(cnt_8bit == _8bit-1)
		cnt_8bit <= 0;
		else
		cnt_8bit <= cnt_8bit + 1;
	end
end
//tx
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		tx <= 0;
	else if(flag_tx)
		case(cnt_8bit)
			0:	tx <= 0;
			1:	tx <= reg_tx_data[0];
			2:	tx <= reg_tx_data[1];
			3:	tx <= reg_tx_data[2];
			4:	tx <= reg_tx_data[3];
			5:	tx <= reg_tx_data[4];
			6:	tx <= reg_tx_data[5];
			7:	tx <= reg_tx_data[6];
			8:	tx <= reg_tx_data[7];
			default:tx <= 1;
		endcase
	else
		tx <= 1;
end
endmodule

4.测试仿真

tx的仿真要比rx的仿真要简单很多,关键在于延迟的计算,如果延迟不对,那么波特率就不是9600,那么数据就会乱套;

`timescale 1 ns/1 ns

module tb_tx();

//输入信号
reg[7:0]  tx_data  ;
reg       trig;
reg       clk  ;
reg       rst_n;

//输出信号
wire      tx;

//参数
parameter CYCLE    = 20;

//待测试的模块例化
tx u2
(
    .clk          (clk           ), 
    .rst_n        (rst_n         ),
    .trig   	  (trig    	 ),
    .tx_data      (tx_data       ),
    .tx           (tx            )
);


//生成本地时钟50M
initial begin
    clk = 0;
    forever
    #(CYCLE/2)
    clk=~clk;
end

//产生复位信号
initial begin
    rst_n = 1;
    #2;
    rst_n = 0;
    #2
    rst_n = 1;
end

initial begin
    tx_data <= 8'd0;
    trig <= 0;
    #20;
    tx_data <= 8'b01010101;
    trig <= 1'b1;
    #937440;	//一共9个比特 ,因此是937440(5208*20*9)的时间
    trig <= 1'b0;
    #2;
    tx_data <= 8'b10101010;
    trig <= 1'b1;
    #937440;
    trig <= 1'b0;
end

endmodule

仿真结果:在modelsim中,先输入的是高位,因此01010101的仿真应该是10101010的tx数据

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值