【厉害了FPGA】Verilog实现接收帧数据的一种方法(帧数据同步搜索检测)

    FPGA和其他设备进行通信的时候,如果传输的是大量数据,肯定需要打包(组帧)进行传输,而且都需要有帧头和校验位来确保帧数据传输正确。今天说一下最近自己做的一个项目涉及到的这个问题。

    当FPGA作为接收端去接收帧数据的时候,即使保证一帧数据的帧头是正确的,而且校验位是正确的也不能百分百保证这帧数据正确接收了,可能情况:1、数据传输有错误,但是错误的数据也得到了一样正确的校验位;2、数据中正好有一位数据是帧头,而我们把这个数据当做了帧头,这个按帧头接收完一帧数据,帧尾的校验位也正好算出来也是对的,等其他小概率事件。对于第一种情况我们可以通过设计好的校验方式(CRC或者其他校验方式)来使这种概率减低,还有数据是突发的还是一直连续不断发送的,这些都是我们在接收机设计的时候必须考虑的。

    为了避免这种情况,在每次接收数据的时候,我们设置接收数据的时候有两种状态,一种是同步态,一种是捕获态(如下图)。在同步态连续接收到几帧数据(在此处我们叫做权值)的时候,才能进入捕获态,在捕获态我们接收到的数据才视作正确的数据。这样我们设计的权值越大,那么第二种情况发生的概率越低,但是付出的代价是丢弃了好多数据帧。


    话不多说,程序的状态转移图如图所示:

    本次是基于Verilog的一个接收机设计,模块按阻塞赋值(顺序执行)的方式。数据是从PC用串口按8位数据的方式传输到FPGA,帧长是344位,即34字节。帧头是两字节,校验位是7位数据,校验和的方式。

always@(posedge i_rx_state_1 or negedge i_reset)//一个i_rx_state_1的上升沿代表接收了一字节数据(阻塞赋值)
begin
	if(!i_reset)
		begin
		rx_frame_temp     = 344'd0;
		rx_frame          = 344'd0;
		work_state        = 8'd0;
		frameheader_cache = 16'd0;
		rx_byte           = 6'd0;
		syn_weight        = 2'd0;
		capture_signal    = 1'b0;
		end
	else 
		begin
		case(work_state)
			
			syn_check_frameheader:
						begin
						syn_weight        = 2'd0;
						rx_frame_temp = 344'd0;
						frameheader_cache = frameheader_cache<<8;
						frameheader_cache[7:0] = iv_rx_data_1;
						if(frameheader_cache==16'hA555)//判断是帧头a555的话,进入同步态,否则继续检测
							begin
							work_state = synchronous_state;
							rx_frame_temp[15:0] = frameheader_cache;
							rx_byte = 6'd2;
							end
						else 
							work_state = syn_check_frameheader;
						end
			synchronous_state:
						begin
						frameheader_cache = 16'd0;//清除缓存
						if(rx_byte>=6'd43)//如果接收满数据,则rx_byte一直处于满状态
							rx_byte = rx_byte;
						else 
							rx_byte = rx_byte+1'b1;
						rx_frame_temp = rx_frame_temp<<8;
						rx_frame_temp[7:0] = iv_rx_data_1;
						if(rx_byte>=6'd43)//接收完一帧数据(满状态)
							begin
							check_byte = ;//计算校验位,自己按照自己需求设计,为了节省代码空间,省去
							if((rx_frame_temp[7:0]==check_byte)&&(rx_frame_temp[343:328]==16'hA555))//校验位正确,等待权值为2的时候进入捕获态,否则继续接收数据
								begin
									syn_weight = syn_weight+1'b1;
									if(syn_weight>=2'd2)//连续两个帧数据接收正确进入捕获态
										work_state = capture_check_frameheader;
									else //权值<2,再次检测下一个帧头
										work_state = syn_check_frameheader;
								end
							else //校验位不正确,权值减一;下一次滑动接收数据,并检验帧头和校验位是否正确,不断循环,直到接收到正确的数据
								begin
								if(syn_weight==2'd0)//权值为0 滑动检测
									begin
									work_state = synchronous_state;
									syn_weight = 2'd0;
									end
								else 
									begin
									syn_weight = syn_weight-1'b1;
									work_state = syn_check_frameheader;
									end
								end
							end
						end
			capture_check_frameheader:
						begin
						syn_weight        = 2'd0;
						rx_frame_temp         = 344'd0;
						capture_signal        = 1'b0;//复位捕获信号
						rx_byte               = 6'd0;//清除接收计数缓存
						frameheader_cache     =frameheader_cache<<8;
						frameheader_cache[7:0]=iv_rx_data_1;
						if(frameheader_cache==16'hA555)//判断是帧头的话,进入同步态,否则继续检测
							begin
							work_state = capture_state;
							rx_frame_temp[15:0] = frameheader_cache;
                                                        rx_byte = 6'd0;//清除接收计数缓存
							end
						else 
							work_state = capture_check_frameheader;
						end
			capture_state:
						begin
						rx_byte = rx_byte+1'b1;
						rx_frame_temp = rx_frame_temp<<8;
						rx_frame_temp[7:0] = iv_rx_data_1;
						if(rx_byte>=43)//接收完一帧数据
							begin
							capture_signal = 1'b1;//产生捕获信号
							check_byte = ;//计算校验位
							if((rx_frame_temp[7:0]==check_byte)&&(rx_frame_temp[343:328]==16'hA555))
								begin
								work_state = capture_check_frameheader;
								rx_frame = rx_frame_temp;
								end
							else 
								begin
								rx_byte = 6'd0;//清除接收计数缓存
								work_state = syn_check_frameheader;
								rx_frame_temp = 344'd0;
								frameheader_cache = 16'd0;
								syn_weight        = 2'd0;
								end
							end
						end
			default:
				begin
				rx_byte = 6'd0;//清除接收计数缓存
				work_state = syn_check_frameheader;
				rx_frame_temp = 344'd0;
				frameheader_cache = 16'd0;
				syn_weight        = 2'd0;
				end	
		endcase
		end
end
                                    
展开阅读全文

没有更多推荐了,返回首页