FPGA实现 串口发送模块

首先搞清楚的是该模块实现的功能:利用FPGA将一个并行的数据(我的理解是可以来自FPGA内部,也可以外部存储器中),以串行的方式发送给PC(或者其他MCU)

串口发送的时序图参照了开源骚客的课程:

baud_cnt 换成了cnt0 

bit_cnt 换成了cnt0

rs232_tx 换成了uart_tx

取消了内部信号:bit_flag(这个信号主要为了指示一个bit的信号发完了,我在计数器中直接用了end_cnt0代替)

 

代码的大体思路:

在tx_trig信号为高的时候(至少为1个周期的高电平)表示有并行的数据tx_data过来了(以上两个信号都是输入信号,真正运行的时候应该是外部给出的,是不用我们提供的,但是我们需要依据这两个信号设计其他的型号,主要是设计输出信号,问题又来了仅仅这两个信号能设计出输出信号吗?当然不能了,所以才设计一系列的内部辅助信号cnto,cnt1,tx_flag等)。

过来的tx_data 用tx_data_reg寄存一下(感觉是为了时序同步),然后没过5208个时钟周期(波特率为9600时),按从低到高的顺序一位一位的把数据传送给uart_tx(当然首先应该把线拉低,表示起始位)

 

代码:

module		uart_tx(
			input			wire			clk			,
			input           wire            rst_n		,
		    input           wire            tx_trig     ,  //传输的触发信号
			input           wire[7:0]       tx_data     ,  //需要传输的并行数据
			output          reg             uart_tx        //并转串后输出的数据
);
/*参数及内部信号定义*/
reg         tx_flag;
reg[12:0]   cnt0;
reg[3:0]    cnt1;
reg[7:0]    tx_data_reg;

wire		add_cnt0;
wire        end_cnt0;
wire        add_cnt1;
wire        end_cnt1;

always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			tx_data_reg<=8'b0;
		end
		
		else if(tx_trig==1&&tx_flag==0)begin
			tx_data_reg<=tx_data;
		end
end





//cnt0  计数5208
always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			cnt0<=0;
		end
		else if(add_cnt0)begin
			   if(end_cnt0)begin
					cnt0<=0;
			   end
			   else begin
					cnt0<=cnt0+1;
			   end
		end
end
assign add_cnt0=tx_flag;
assign end_cnt0=add_cnt0&&cnt0==5208-1;


always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			cnt1<=0;
		end
		else	if(add_cnt1)begin
			if(end_cnt1)begin
				cnt1<=0;
			end
			else begin
				cnt1<=cnt1+1;
			end
			
		end
end

assign add_cnt1=end_cnt0;
assign end_cnt1=add_cnt1&&cnt1==9-1;



always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			tx_flag<=0;
		end
		else	if(tx_trig==1&&tx_flag==0) begin
			tx_flag<=1;
		end
		
		else if(cnt1==8&&cnt0==5207) begin
			tx_flag<=0;
		end
		
end


always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			uart_tx<=1;
			
		end	
		else if(tx_flag==1)begin
			case(cnt1)
				0:uart_tx<=0;                        //开始位
				1:uart_tx<=tx_data[0];               //从低位往高位传输
				2:uart_tx<=tx_data[1];
				3:uart_tx<=tx_data[2];
				4:uart_tx<=tx_data[3];
				5:uart_tx<=tx_data[4];
				6:uart_tx<=tx_data[5];
				7:uart_tx<=tx_data[6];
				8:uart_tx<=tx_data[7];
				default:
				  uart_tx<=1;        //结束后回高位
			endcase
		end
		
end
endmodule

测试模块:

`timescale		1ns/1ns
module tb_uatr_tx();

reg			clk			;
reg			rst_n		;
reg			tx_trig		;
reg[7:0]	tx_data		;
wire		uart_tx		;


initial begin
		clk=    0;
		rst_n=  0;
		#100
		rst_n=  1;
		#100
		tx_trig=1;
		tx_data=8'h55;
		#100
		tx_trig=0;
end
always		#10		clk=~clk		;

//模块例化

uart_tx		uart_tx_inst(
			.	   clk			      (clk)        ,
			.      rst_n		      (rst_n)      ,
		    .      tx_trig            (tx_trig)    ,  //传输的触发信号
			.      tx_data            (tx_data)    ,  //需要传输的并行数据
			.      uart_tx            (uart_tx)       //并转串后输出的数据
);      
endmodule

 

modelsim仿真:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值