基于FPGA的UART数据串口通信

1.通过uart芯片实现数据回传测试,最终通过串口助手发生数据,第一部先将原理图P出。

2.代码仿真,对各个信号进行原理仿真,各个信号的名称意义。

(1).rx_data:就是上位机传来的数据信号。由于数据传输的时间与FPGA的时钟信号不一定同步,可能产生亚稳态,所以要将传来的信号进行握手延时。最终实现信号同步。rx_data_2与rx_data_3即为延时信号。(2)rx_en使能信号就是信号来的时候开始采集,其条件就是握手信号的不同,一个为0一个为1。(3)计数器是为了同步波特率9600和bit计数。(4).tmp_data为临时缓存数据的寄存器。(5).bit_flag是数据采集信号。

3.仿真信号,必须与原理信号一直,仿真文件需要随机产生

`timescale 1ns/1ns
module tx_tb;

			reg sclk;
			reg rst_n;
			reg rx_in;
			 
			wire flag_o;
			wire [7:0] data_o;

initial	
		begin
			sclk=1'b0;
			rst_n<=1'b0;
			rx_in<=1'b0;
			#200
			rst_n<=1'b1;
		end
always #10 sclk=~sclk;

reg [12:0] 	cnt;
reg [3:0]  	bit_cnt;
reg  		start;

parameter	CNT=5207;
parameter   BIT_CNT=9;

always@(posedge sclk or negedge rst_n)
		if(!rst_n)
			cnt<=13'd0;
		else if(cnt==CNT)
			cnt<=13'd0;
			else cnt<=cnt+1'b1;

always@(posedge sclk or negedge rst_n)
		if(!rst_n)
			bit_cnt<=4'd0;
			else if(bit_cnt==BIT_CNT&&cnt==CNT)
				bit_cnt<=4'd0;
				else if(cnt==CNT)
					bit_cnt<=bit_cnt+1'b1;
			 					
always@(posedge sclk or negedge rst_n) //产生起始标志位
		if(!rst_n)
			start<=1'b1;
		else if(cnt>=1&&cnt<=9)
			start<=1'b0;
			else start<=1'b1;
			
always@(posedge sclk or negedge rst_n) //产生随机数
		if(!rst_n)
			rx_in<=1'b0;
		else case (bit_cnt)
				4'd2: rx_in<={$random};
				4'd3: rx_in<={$random};
				4'd4: rx_in<={$random};
				4'd5: rx_in<={$random};
				4'd6: rx_in<={$random};
				4'd7: rx_in<={$random};
				4'd8: rx_in<={$random};
				4'd9: rx_in<={$random};
				default:rx_in<=1'b0;  //只在规定范围内产生数据 其他状态清零
			endcase
			
tx_crtl tx_crtl_inst(
					
					.sclk		(sclk),
					.rst_n		(rst_n),
					.rx_in		(rx_in),
					
					.flag_o		(flag_o),
					.data_o     (data_o)
);

endmodule

4.要时刻记住每个信号对比,而且延时握手信号处于在复位状态应该是高电位。

5.这次的测试文件写的有问题,修改后如下:

`timescale 1ns/1ns
module tx_tb;

			reg sclk;
			reg rst_n;
			reg rx_in;
			 
			wire flag_o;
			wire [7:0] data_o;

initial	
		begin
			sclk=1'b0;
			rst_n<=1'b0;
			rx_in<=1'b0;
			#200
			rst_n<=1'b1;
		end
always #10 sclk=~sclk;

reg [12:0] 	cnt;
reg [3:0]  	bit_cnt;


parameter	CNT=5207;
parameter   BIT_CNT=9;

always@(posedge sclk or negedge rst_n)
		if(!rst_n)
			cnt<=13'd0;
		else if(cnt==CNT)
			cnt<=13'd0;
			else cnt<=cnt+1'b1;

always@(posedge sclk or negedge rst_n)
		if(!rst_n)
			bit_cnt<=4'd0;
			else if(bit_cnt==BIT_CNT&&cnt==CNT)
				bit_cnt<=4'd0;
				else if(cnt==CNT)
					bit_cnt<=bit_cnt+1'b1;
			 					

			
always@(posedge sclk or negedge rst_n) //产生随机数
		if(!rst_n)
			rx_in<=1'b0;    //复位状态应该为0 ,仿真产生数据有问题
		else if(bit_cnt==0&&cnt==CNT)    //起始位仿真 
				rx_in<=1'b0;
			else if(bit_cnt>=1&&bit_cnt<=8&&cnt==CNT)//case (bit_cnt)
			 	rx_in<={$random};
				else if(bit_cnt==9&&cnt==CNT)  //结束位仿真
					rx_in<=1'b1;
			
uart_tx_train	uart_tx_train_inst(

				.sclk		(sclk),
				.rst_n		(rst_n),
				.rx_in		(rx_in),
			
				.data_o		(data_o),
				.flag_o     (flag_o)

);

endmodule

6.最后为顶层文件设计,需要考虑明白FPGA的接受端和发送端如何与uart芯片进行连线。

7.uart芯片的发生端程序

module tx_crtl(

		input wire sclk,
		input wire rst_n,
		input wire rx_in,
		
		output reg flag_o,
		output reg [7:0] data_o
);

reg [12:0] cnt;
reg [3:0]  bit_cnt;
reg rx_in_1,rx_in_2;
reg rx_en;     //使能信号值有问题
reg bit_flag;
reg [7:0]tmp_data;
reg tmp_flag;

parameter	CNT=5207;
parameter   BIT_CNT=9;
parameter   bit_flag_cnt=2603;  //	产生bit采集标志位
//parameter   clean_flag=2610;

always@(posedge sclk or negedge rst_n)
		if(!rst_n)
			rx_in_1<=1'b1;
		else rx_in_1<=rx_in;
always@(posedge sclk or negedge rst_n)  //输入信号延时
		if(!rst_n)
			rx_in_2<=1'b1;
		else rx_in_2<=rx_in_1;

always@(posedge sclk or negedge rst_n)   //产生计数使能信号
		if(!rst_n)
			rx_en<=1'b0;
		else if(rx_in_1==1'b0&&rx_in_2==1'b1)
			rx_en<=1'b1;
			else if(bit_cnt==BIT_CNT&&cnt==CNT)
			 rx_en<=1'b0;
			 
always@(posedge sclk or negedge rst_n)
		if(!rst_n)	
			cnt<=13'd0;
			else if(rx_en==1'b0)
				  cnt<=13'd0;
				  else if(cnt==CNT)
						cnt<=13'd0;
				  	else if(rx_en==1'b1)
				  			cnt<=cnt+1'b1;
				 
always@(posedge sclk or negedge rst_n)   //位宽计数
		if(!rst_n)	
			bit_cnt<=4'd0;
				else if(rx_en==1'b0)	
					bit_cnt<=4'd0;
				else if(bit_cnt==BIT_CNT&&cnt==CNT)	
					bit_cnt<=4'd0;	
					else if(cnt==CNT)
						bit_cnt<=bit_cnt+1'b1;

always@(posedge sclk or negedge rst_n)   //产生bit标志位
		if(!rst_n)
			bit_flag<=1'b0;
			else if(cnt==bit_flag_cnt)	
				bit_flag<=1'b1;
				else bit_flag<=1'b0;	

always@(posedge sclk or negedge rst_n)   //数据拼接
		if(!rst_n)	
			tmp_data<=8'd0;
		else if(bit_flag==1'b1&&bit_cnt>=4'd1&&bit_cnt<=4'd8)
				tmp_data<={rx_in_2,tmp_data[7:1]}; 		//少写分号
														//else if(bit_cnt==BIT_CNT&&cnt==clean_flag)  数据不清零条件
														//		tmp_data<=8'd0;

always@(posedge sclk or negedge rst_n)   //数据拼接完成标志
		if(!rst_n)	
		 tmp_flag<=1'b0;
		 else if(bit_flag==1'b1&&bit_cnt==BIT_CNT)
		 	tmp_flag<=1'b1;
		 	else tmp_flag<=1'b0;

always@(posedge sclk or negedge rst_n)
		if(!rst_n)	
			data_o<=8'd0;
		else if(tmp_flag==1'b1)
			data_o<=tmp_data;

always@(posedge sclk or negedge rst_n)
		if(!rst_n)			
			flag_o<=1'b0;
			else flag_o<=tmp_flag;	 
endmodule

猜你喜欢

转载自blog.csdn.net/Headogerz/article/details/81772483