基于ask 的调制解调 抽样判决与同步设计

这里写一个ask 的调制解调,首先是主要关于ASK在抽样判决的逻辑的撰写,
:首先在没有接收到数据的时候,我们的收到的信号肯定的是比较小的值(因为噪声应该是比较的值)。
所以我们这里要先设计一个开始逻辑,就是什么时候才是接收到数据,而不是空的噪声。
思路:这里是对接收到的值进行一个累加,然后取平均值,再设一个门限值,如果这个平均值大于前一个门限值,就是代表有数据进来的,而不是全是噪音了,接下来就可以进行符号判别了。当检测到有数据输入后,我们就要开始取样判决了。

这是一些自己画的波形:

 

 

下面给出代码并给与


// 实际只需要累加到8192,但是多加2个时钟周期,是为了后面累加与判决门限值
always @(posedge sclk) begin
	if (rst_n == 1'b0) begin
		work_cnt <='d0;
	end else if(work_on == 1'b1) begin
		work_cnt <= 'd0;
	end else if (work_cnt == 'd8194) begin
		work_cnt <= 'd0;
	end else begin
		work_cnt <= work_cnt + 1'b1;
	end
end

//acc the din_data to acquire the gate 
//
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		work_sum <= 33'd0 ; 
	end else if(work_on == 1'b1)begin
		work_sum <= 'd0;
	end else if(work_cnt == 'd8194)begin  //获得了一次门限值后清零
		work_sum <= 'd0;
	end else if(work_cnt == 'd8193)begin  //保持
		work_sum <= work_sum;
	end else if(work_cnt == 'd8192) begin  //输入值累加8192次,然偶除以8192,取平均值。
		work_sum <= work_sum >> 13;
	end else if(work_on == 1'b0)begin
		work_sum <= work_sum + dina_t;
	end
end

always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		work_gate <= 23'h7f_ffff; //23位的最大值
	end else if(work_cnt == 'd8193) begin
		work_gate <= {work_sum[20:0],2'b00}; //门限值是8192次数据的4倍 
	end 									//在8193时候进行更新wor_gate值,(所以万一没有检测到,下次这么大会开启?)
end
// 
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		work_on <= 1'b0; 
	end else if(byte_cnt > 1'b1 && byte_cnt == (data_len + 1) && byte_flag == 1'b1 )begin
		work_on <= 1'b0;
	end else if(detect_sync_cnt == 'd52000 && sync_flag == 1'b0) begin
	//end else if(detect_sync_cnt == 'd52000 && sync_flag == 1'b1) begin
		work_on <= 'd0;
	end	else if(work_cnt == 'd8193 && (work_sum > work_gate)) begin //当计数到8193,此时work_gate
		work_on <= 1'b1; 											///还是原来的值,上一个门限值
	end 															//。
end

取样判决:首先符号的判断门限值选取,可以选择均值,但是均值门限值的选取肯定要大于一个符号周期,其次这样才能保证符号判决的正确,否则取均值长度过小导致判决门限值变化很快,导致判据出错。且如果连续发送多个 0 时,接收到的波形值都比较小,再取均值就可能导致判决门限过小,从而导致判决错误,所以对于符号周期比较长
的系统来说取均值的方法就不太适用了。这里是选取的5个符号周期的最大值的1/4的作为门限值。并且这个门限值也是5个符号周期更新一次,使用此统计门限值用于检测到同步头前的判决。检测到同步头之后更新的值小于旧的门限值的二分之一或更新的值大于旧的门限值的二倍,仍保持旧的门限值,等待下一次更新。这样能保证在一个符号周期内只有一个判决值,且发送多个 0 时,不会产生误判。
判断过程:由于我们的使用的设备是一个符号对应800个时钟周期,所以我们要设计一个计数器计数5个符号周期,然后设置一个标志位,每5个符号周期翻转一次,这样分别在标志位位0,1时分别找到5个符号周期的最大值,并且在一个启动了帧同步后才开始进行比较,在计数时到5个符号周期结束时开始与上一次的最大值2倍

牢记:在进行门限值赋值时,一定是等于上5个符号周期的最大值的1/4,这里要牢记(调试了2天,呜呜呜);这里一给出一些重要的逻辑波形图

 

 

下面也给出一些逻辑代码

//统计5个符号周期的平均功率作为平均功率作为符号判决标准
//由于我们的AD9361设置为了单通道模式,采样时钟为40M,
//由于两个时钟才能传,完一个 12 位的有效数据,
//所以实际的时钟频率为 80MHz,
//符号周期为 800 个时钟
//在 adc_valid 为低时
//数据保持,这样就当作有效数据被复制一次使用,也就是说数据频率为 100Kbps
//时,符号周期为 800 个时钟.
//所以我们这里统计5个符号周期的需要用计数器计数计数4000,即0到3999
//
//判决门限
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		gate_cnt <= 'd0;  
	end else if(work_on == 1'b0) begin
		gate_cnt <= 'd0; 
	end else if(work_on == 'd3999) begin
		gate_cnt <= 'd0; 
	end else begin
		gate_cnt <= gate_cnt + 1'b1; 
	end
end
//计数到4000,取5个符号周期,要取两个的值进行比较,所以要进行翻转
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		gate_flag <= 1'b0; 
	end else if(work_on == 1'b0)begin
		gate_flag <= 1'b0; 
	end else if(gate_cnt == 'd3999) begin
		//gate_flag <= 1'b1;
		gate_flag <= ~gate_flag;
	end
end
// delay a clk
always@(posedge sclk )begin
	gate_flag_t <= gate_flag;
end
//
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		gate_a <=  'd0; 
	end else if(gate_flag_t == 1'b1 && gate_flag == 1'b0)begin  //下降沿
			gate_a <= 'd0;										//将门限值的最大值清零
	end else if(sync_flag == 1'b1 && gate_cnt == 'd3999 && gate_flag == 1'b0)begin //判断准则,若这个周期内的最大值大于
		if(gate_a > (gate_b << 1) || gate_a < (gate_b >> 1))begin                //大于上个周期的最大值的2倍或者小于其最小值
			gate_a <= gate_b;												//的1/2,就将gate_b赋值给gate_b
			end
		end else if(dina_tvalid == 1'b1 && gate_flag == 1'b0) begin //在5个符号周期内,比较其值
		if(gate_a < dina_t)begin                                    //找出输入数据的最大值,然后赋值给gate_a
			gate_a <= dina_t;
		end else begin
			gate_a <= gate_a;
		end
	end
end

//
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		gate_b <=  'd0; 
	end else if(gate_flag_t == 1'b0 && gate_flag == 1'b1)begin  //上升沿  //gate_b 开始时计数
			gate_b <= 'd0;  // clear 0
	end  else if(sync_flag == 1'b1 && gate_cnt == 'd3999 && gate_flag == 1'b1)begin //判断准则,若这个周期内的最大值大于
		if(gate_b > (gate_a << 1) || gate_b < (gate_a >> 1))begin 			//大于上个周期的最大值的2倍或者小于其最小值
			gate_b <= gate_a;												//的1/2,就将gate_b赋值给gate_b
			end
		//end else if(dina_tvalid == 1'b1 && gate_flag == 1'b0) begin //在下一个5个符号周期内,比较其值
		end else if(dina_tvalid == 1'b1 && gate_flag == 1'b1) begin
		if(gate_b < dina_t)begin                                    //找出输入数据的最大值,然后赋值给gate_b
			gate_b <= dina_t;										//
		end else begin
			gate_b <= gate_b;
		end
	end
end
//用上述所取出来的值的1/4作为判决值,
//always@(posedge sclk )begin
//	if(rst_n == 1'b0)begin
//		gate_t <= 'd0; 
//	end else if(gate_flag == 1'b0) begin
//		gate_t <= gate_a >> 2; 
//		gate_t <= gate_b >> 2;
//end

//用上述所取出来的值的1/4作为判决值,
//这里的门限值是与上一次比较,不是与现在的比较,切记,切记,这里调试了2天,一直没有找到问题
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		gate_t <= 'd0; 
	end else if(gate_flag == 1'b1) begin
		gate_t <= gate_a >> 2;    
	end else if(gate_flag == 1'b0) begin
		gate_t <= gate_b >> 2;
	end
end
 /// 这里为判决
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		bit_in<= 1'b0; 
	end else if(dina_t >= gate_t) begin
		bit_in <= 1'b1;
	end else begin
		bit_in <= 1'b0;
	end
end

重点:
符号采样:符号采样,我们应该在每个符号周期采样一次,并且尽可能的在一个符号周期的中间进行采样,因为我们的符号周期对应我们的800个时钟周期,所以我们需要一个符号的计数器,在计数到400就进行采样。但是在实际的过程的中,我们就收的数据并不是突变的,而是缓慢的变化,所以说所以判决出的每一个二进制数据并不是刚好等于400的,可能多也可能少,这就需要设计一个补偿的机制,来保证符号采样在判决后的二进制数据的正中间。
判决机制:对于判决出来的bit进行计数,只要变化,计数器就清零,重新开始计数,并且计数到800个时钟周期也清零,接下来进行。

(1)数据保持:就是出来的一直保持一个状态,比如连续的几个0或者1,这样就是前面我们的符号计数器计数到800,然后除以2(左移1位),就是一个符号的正中间,就可以进行判决
(2):当边沿变化时,计数值比较小时(小于400),我们可以将他认为是上一个bit的延展,
(3):当边沿变化时,计数值比较大(大于400小于799)时,要将此时的计数值除以二时,这个时刻为判决的时刻。

代码:

//利用fifo 来进行延拍,800个时钟周期
instance fifo /
// fifo wr:    1 x 1024
//
sfifo_wr1x1024 sfifo_wr1x1024_inst (
  .clk(sclk),      // input wire clk
  .din(bit_in),      // input wire [0 : 0] din
  .wr_en(wr_fifo_en),  // input wire wr_en
  .rd_en(rd_fifo_en),  // input wire rd_en
  .dout(bit_delay),    // output wire [0 : 0] dout
  .full(full),    // output wire full
  .empty(empty)  // output wire empty
);
//
always@(posedge sclk )begin
	if(rd_fifo_en == 1'b1 )begin
		bit_delay_t <= bit_delay;
	end else begin
		//bit_delay_t <=bit_delay_t;
		bit_delay_t <='d0;
	end
end

//当work on  == 1 时,开始写FIFO
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		wr_fifo_en <= 1'd0; 
	end else if(work_on == 1'b0) begin
		wr_fifo_en <= 1'd0;
	end else begin
		wr_fifo_en <= 1'd1;
	end
end
//------------------------
//从fifo里面读取出来的数据进行一个延拍
//--------------------------
always@(posedge sclk)begin
	bit_in_t <= bit_in;
end
//判断数据的上升沿与下降沿
always@(posedge sclk )begin
	//if(rst_n == 1'b0)begin
	//	rising <= 1'b0 ; 
	//end else 
	if(work_on == 1'b0) begin
		rising <= 1'b0 ;
	end else if(bit_in == 1'b1 && bit_in_t == 1'b0) begin
		rising <= 1'b1 ;
	end else begin
		rising  <= 1'b0;
	end
end
///

always@(posedge sclk )begin
	//if(rst_n == 1'b0)begin
	//	falling <= 1'b0 ; 
//	end else 
if(work_on == 1'b0) begin
		falling <= 1'b0 ;
	end else if(bit_in == 1'b0 && bit_in_t == 1'b1) begin
		falling <= 1'b1 ;
	end else begin
		falling <= 1'b0;
	end
end

//判断两个沿之间的时钟数,取样时尽可能取一个数据的中间的那位
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		count <= 'd0; 
	end else if(work_on == 1'b0) begin
		count <= 'd0;
	end else if(rising == 1'b1 || falling == 1'b1)begin
		count <= 'd0;
	end else if(count == 'd799) begin
		count <= 'd0;
	end else begin
		count <= count +1'b1;
	end
end
// 采样计数器,判决在何时取样
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		samp_count <= 'd0; 
	end else if(work_on == 1'b0) begin
		samp_count <= 'd0;
	end else if(count == 'd799) begin
		samp_count <= 'd399;
	end else if(rising == 1'b1 ||falling == 1'b1)begin
		if(count < 'd400) begin     //超过了一个符号周期的长度
			samp_count <= (800 + count ) >> 1;
		end	else if (count >= 'd400) begin  
			samp_count <= (count >>1); //不足一个符号周期的长度
		end
	end
end

//利用FIFO,将读使能延迟一个符号周期
always@(posedge sclk ) begin
	if(rst_n == 1'b0)begin
		rd_delay_cnt <= 'd0;
	end else if(work_on == 1'b0)begin
		rd_delay_cnt <= 'd0;
	end else if(rd_delay_cnt == 'd800)begin
	//	rd_delay_cnt <= rd_delay_cnt; 
		rd_delay_cnt <= 'd800; 
	end else if(wr_fifo_en == 1'b1)begin
		rd_delay_cnt <= rd_delay_cnt + 1'b1;
	end
end
//写使能一个符号周期后,开启读使能
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		rd_fifo_en <= 'd0 ; 
	end else if(empty == 1'b1)begin
		rd_fifo_en <= 'd0 ;
	end else if(rd_delay_cnt == 'd799) begin
		rd_fifo_en <= 1'b1;
	end
end



// fifo出来的数据,延迟了一个符号周期,判断其上升沿
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		 rising_delay <= 1'b0; 
	end else if(rd_fifo_en == 1'b0) begin
		 rising_delay <= 1'b0; 
	end else if(bit_delay == 1'b1 && bit_delay_t ==1'b0)begin
		 rising_delay <= 1'b1; 
	end else begin
		rising_delay <= 1'b0; 
	end
end

always @(posedge sclk)  begin
	if(rd_fifo_en == 1'b1 ) begin
			bit_delay_t <= bit_delay;
	end
end
// fifo出来的数据,延迟了一个符号周期,判断其下降沿
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		 falling_delay <= 1'b0; 
	end else 
	if(rd_fifo_en == 1'b0) begin
		 falling_delay <= 1'b0; 
	end else if(bit_delay == 1'b0 && bit_delay_t ==1'b1)begin
		 falling_delay <= 1'b1; 
	end else begin
		falling_delay <= 1'b0; 
	end
end
//这个没懂,为啥子要延迟
always@(posedge sclk )begin
	if(rst_n == 1'b0)begin
		count_delay <= 'd0; 
	end else if(rd_fifo_en == 1'b0) begin
		count_delay <= 'd0; 
	end else if(falling_delay == 1'b1 || rising_delay == 1'b1) begin
		count_delay <= 'd0;
	end else if(count_delay == 'd799) begin
		count_delay <= 'd0;
	end else begin
		count_delay <= count_delay + 1'b1;
	end
end
 //采样标志位
 always@(posedge sclk )begin
 	if(rst_n == 1'b0)begin
 		samp_flag <= 1'd0; 
 	end else if(rd_fifo_en == 1'b0) begin
 		samp_flag <= 1'd0;
 	end else if(rd_fifo_en == 1'b1 && count_delay == samp_count) begin
 		samp_flag <= 1'd1;
 	end else begin
 		samp_flag <= 1'd0;
 	end
 end


由于我们发送的数据帧格式是7个巴克玛还有一个数据头(D5)(1101_0101),要检测到了之后才是真正的数据。
取样判决后我们进行数据头部巴克玛与数据头都直接用一个状态机检测,如果帧头部与数据头都检测完,下面就可以开启帧同步标志了,下面接收到的数据就是我们发送的数据了。
由于我们的数据是1帧数据8位,所以下面我们要进行判断数据的大小,只需要设计一个计数器,判决出8个数据拉高一个标志就行了

下面代码为检测巴克玛与数据头代码

always@(posedge sclk)begin
 	if(rst_n == 1'b0) begin
 		barker_state <= BS0;
 	end
 	if(rd_fifo_en == 1'b0 || sync_flag == 1'b1) begin
 		barker_state <= BS0;
 	end else begin //1110010 检测巴克玛
 		case(barker_state)
 		BS0:begin
 			if(samp_flag == 1'b1 && bit_delay_t == 1'b1)begin
 				barker_state <= BS1;
 			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b0) begin
 				barker_state <= BS0;
 			end
 		end
 		BS1:begin
 			if(samp_flag == 1'b1 && bit_delay_t == 1'b1)begin
 				barker_state <= BS2;
 			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b0) begin
 				barker_state <= BS0;
 			end
 		end
 		BS2:begin
 			if(samp_flag == 1'b1 && bit_delay_t == 1'b1)begin
 				barker_state <= BS3;
 			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b0) begin
 				barker_state <= BS0;
 			end
 		end
 		BS3:begin
 			if(samp_flag == 1'b1 && bit_delay_t == 1'b0)begin
 				barker_state <= BS4;
 			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b1) begin
 				barker_state <= BS0;
 			end
 		end
 	    BS4:begin
 			if(samp_flag == 1'b1 && bit_delay_t == 1'b0)begin
 				barker_state <= BS5;
 			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b1) begin
 				barker_state <= BS0;
 			end
 		end
 		BS5:begin
 			if(samp_flag == 1'b1 && bit_delay_t == 1'b1)begin
 				barker_state <= BS6;
 			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b0) begin
 				barker_state <= BS0;
 			end
 		end
 		BS6:begin
 			if(samp_flag == 1'b1 && bit_delay_t == 1'b0)begin
 				barker_state <= BS7;
 			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b1) begin
 				barker_state <= BS0;
 			end
 		end
 		BS7:begin
 			barker_state <= BS0;
 		end
 		default:barker_state <= BS0;
 	endcase	
 	end
 end


 
  
 
//sync
always@(posedge sclk )begin //1101_0101
	if(rst_n == 1'b0)begin
		sync_state <= SS0; 
	end else if(rd_fifo_en == 1'b0 || sync_flag == 1'b1) begin
		sync_state <= SS0; 
	end else begin//d5:1101 0101
		case(sync_state)
		SS0:begin
			if(samp_flag == 1'b1 && bit_delay_t == 1'b1)begin
				sync_state <= SS1;
			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b0) begin
				sync_state <= SS0;
			end
		end
		SS1:begin
			if(samp_flag == 1'b1 && bit_delay_t == 1'b1)begin
				sync_state <= SS2;
			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b0) begin
				sync_state <= SS0;
			end
		end
		SS2:begin
			if(samp_flag == 1'b1 && bit_delay_t == 1'b0)begin
				sync_state <= SS3;
			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b1) begin
				sync_state <= SS0;
			end
		end
		SS3:begin
			if(samp_flag == 1'b1 && bit_delay_t == 1'b1)begin
				sync_state <= SS4;
			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b0) begin
				sync_state <= SS0;
			end
		end
		SS4:begin
			if(samp_flag == 1'b1 && bit_delay_t == 1'b0)begin
				sync_state <= SS5;
			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b1) begin
				sync_state <= SS0;
			end
		end
		SS5:begin
			if(samp_flag == 1'b1 && bit_delay_t == 1'b1)begin
				sync_state <= SS6;
			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b0) begin
				sync_state <= SS0;
			end
		end
		SS6:begin
			if(samp_flag == 1'b1 && bit_delay_t == 1'b0)begin
				sync_state <= SS7;
			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b1) begin
				sync_state <= SS0;
			end
		end
		SS7:begin
			if(samp_flag == 1'b1 && bit_delay_t == 1'b1)begin
				sync_state <= SS8;
			end else if(samp_flag == 1'b1 && bit_delay_t == 1'b0) begin
				sync_state <= SS0;
			end
		end
		SS8:begin
			sync_state <= SS0;
		end
		default:begin
			sync_state <= SS0;
		end
		endcase
	end
end

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值