FPGA解析B码----连载3

前言

    这两天没有更新,主要是在调试B码的时间计算程序,今天刚刚将B码的时间解析出来。本来计划先输出1PPS信号,结果发现之前的B码解析遗漏了很多判断,所以只能先解析出各个信号,才能正确输出1PPS。现在将解析B码时间的程序的过程一一介绍。

第一章:时间顺序

    由于FPGA都是并行计算,所以对于搞习惯while(1)的小伙伴并不那么友好,所以自己总结了一个顺序执行的方法,并且B码的接收也是顺序接收的,所以必须加入顺序执行程序。

    方案两种:

    (1)接收到两个P帧之后启动定时器,然后根据定时器判断每个帧的状态,这种比较依赖于定时器的启动和B码的正确性,所以摒弃了这种结构;

    (2)利用下降沿关系,顺延下降沿。

    接收B码中我采用了第2种方法。先看顺延结构:

reg        resettime_en_d0; 
reg        resettime_en_d1; 
wire       resettime_falling_flag;(第一个下降沿)
wire       resettime_rasing_flag;
assign resettime_falling_flag = (~resettime_en_d0) & resettime_en_d1;
assign resettime_rasing_flag  = (~resettime_en_d1) & resettime_en_d0;
always @(posedge clk or negedge rst_n) begin         
    if (!rst_n) begin
        resettime_en_d0 <= 1'b0;                                  
        resettime_en_d1 <= 1'b0; 
    end                                                      
    else begin                                               
        resettime_en_d0 <= timebeginflag;(源下降沿)                               
        resettime_en_d1 <= resettime_en_d0;
        		  
    end
end

    中间有第一个下降沿,当然随便你用哪个下降沿,B码的每个下降沿都可以,你自己定义的下降沿也可以。

reg        resettime1_en_d0; 
reg        resettime1_en_d1; 
wire       resettime1_falling_flag;(第二个下降沿)
wire       resettime1_rasing_flag;
assign resettime1_falling_flag = (~resettime1_en_d0) & resettime1_en_d1;
assign resettime1_rasing_flag  = (~resettime1_en_d1) & resettime1_en_d0;
always @(posedge clk or negedge rst_n) begin         
    if (!rst_n) begin
        resettime1_en_d0 <= 1'b0;                                  
        resettime1_en_d1 <= 1'b0; 
    end                                                      
    else begin                                               
        resettime1_en_d0 <= resettime_falling_flag;                               
        resettime1_en_d1 <= resettime1_en_d0;
        		  
    end
end

    这样就在下降沿之后又创造出一个下降沿,如果不保证不出错的话就只能这样做。当然大神估计不屑于这种方式,但是这种是最快出程序并且最不容易出错的方式。

    优点:不容易出错,不需要太多考虑到FPGA的并行执行规则。

第二章:锁存B码,判断起始P帧

(*noprune*)reg  [3:0]  bcodelevellatch1;
(*noprune*)reg  [3:0]  bcodelevellatch2;

always@(posedge clk or negedge rst_n)
begin
	if (rst_n == 1'b0)begin
		bcodelevellatch1 <= 1'd0;
		bcodelevellatch2 <= 1'd0;
	end
	else if (resettime_falling_flag == 1'b1)begin      
		bcodelevellatch1 <= bcodelevel;
		bcodelevellatch2 <= bcodelevellatch1;                     
   end
end

    首先是上篇文章中判断出来一个脉宽是0 ,1 ,还是P码之后,造出延后的一个下降沿resettime_falling_flag,将得到的数据锁存到latch中。

(*noprune*)reg    bcodereadyflag;
always@(posedge clk or negedge rst_n)
begin
	if (rst_n == 1'b0)
		bcodereadyflag <= 1'd0;
	else if (resettime1_falling_flag == 1'b1)begin 
      if((bcodelevellatch1 >= 4'd3)&&(bcodelevellatch2 >= 4'd3))	
	       bcodereadyflag <= 1'd1; 
	   else bcodereadyflag <= 1'd0;
   end		                  
end

    锁存后,根据上文中制造的延后的第二个下降沿,判断两个锁存值是否都是P帧。如果是,将标志位置1,如果不是继续为0。当然这个标志只出现一个周期。

    至此,B码的起始帧已经判断完毕。

第三章:锁存B码各个信息码

    首先在采集到一个B码之后,必须加入一个计数变量,因为B码1s一共100个,所以需要将100个B码信息全部锁存。

(*noprune*)reg [7:0] bcodebitcnt;  /*synthesis noprune*/
(*noprune*)reg       bcodeflag;
always@(posedge clk or negedge rst_n)
begin
	if (rst_n == 1'b0)begin
		bcodebitcnt <= 8'd0;  
        bcodeflag	<= 1'd0;	
	end
	else if (bpluse_falling_flag == 1)begin
		bcodebitcnt <= bcodebitcnt + 1'b1; 
		bcodeflag	<= 1'd0;	
	end
	else if (bcodereadyflag == 1)
	   bcodebitcnt  <= 8'd3;
	else if (bcodebitcnt == 8'd101)begin
	   bcodebitcnt  <= 0;
	   bcodeflag	<= 1'd1;
	end
   else begin
      bcodebitcnt <= bcodebitcnt; 	
	  bcodeflag	  <= 1'd0;
	end
end

    分开说明:B码的下降沿时,bcodebitcnt加1,在没有锁存到两个P帧时,此变量一直加,到101时变为0,也就是没有检测到2个P帧时随意存储。当检测到bcodereadyflag变为1时,即锁存在两个P帧时,将cnt变为3,重新进行存储。因为1和2两个位存储两个P帧,所以这个地方变为3。

    B码的下降沿时,bcodeflag变为0,当存储到101个时,变为1,即100个码元存储完毕,可以进行下一步运算,当然此处也为一个周期的高电平。

    分析:为啥是101?为啥不是100?当变为101时,下一个周期状态立马变为100了,所以下次B码下降沿来的时候,不会存储到101的单元里面。

reg        resettime2_en_d0; 
reg        resettime2_en_d1; 
wire       resettime2_falling_flag;
wire       resettime2_rasing_flag;
assign resettime2_falling_flag = (~resettime2_en_d0) & resettime2_en_d1;
assign resettime2_rasing_flag  = (~resettime2_en_d1) & resettime2_en_d0;
always @(posedge clk or negedge rst_n) begin         
    if (!rst_n) begin
        resettime2_en_d0 <= 1'b0;                                  
        resettime2_en_d1 <= 1'b0; 
    end                                                      
    else begin                                               
        resettime2_en_d0 <= resettime1_falling_flag;                               
        resettime2_en_d1 <= resettime2_en_d0;
        		  
    end
end

    再顺延一个下降沿。现在说明5个下降沿的作用。

    第1个下降沿:bcodein。

    第2个下降沿:bpluse_falling_flag,这个下降沿延后了B码下降沿一个周期。B码的下降沿。B码的上升沿启动time定时器,B码的下降沿停止time定时器。此时判断B码的时间,看看是2ms,5ms,还是8ms。当然这个时候判断时间不是很准确,但是每个硬件电路都会有延迟,这个地方将time的判断时间范围扩大点,这样就可以判断出来大致的B码的值。

    同时将锁存计数器bcodebitcnt加1,并且判断是否存储到100个码元,如果是第100个码元,置位接收完毕标志位:bcodeflag。

    第3个下降沿:resettime_falling_flag,锁存B码的两个值。

    第4个下降沿:resettime1_falling_flag,锁存B码的两个值后,判断两个B码是否为两个P标志位。此时如果两个B码为P标志位,将bcodebitcnt置为3,那么下次B码采集后才放入bcodebitcnt=3的寄存器中(此处涉及到下降沿的并行问题,逻辑分析之后能明白就行,编写的时候自己想放那哪个寄存器都行,只要能接收对就好)。

    第5个下降沿:resettime2_falling_flag,将B码的值存入到bcodebitcnt对应的寄存器中。对应程序如下:

(*noprune*)reg  [3:0]  b_data_rec1;
(*noprune*)reg  [3:0]  b_data_rec2;
(*noprune*)reg  [3:0]  b_data_rec3;
(*noprune*)reg  [3:0]  b_data_rec4;
(*noprune*)reg  [3:0]  b_data_rec5;
(*noprune*)reg  [3:0]  b_data_rec6;
......
(*noprune*)reg  [3:0]  b_data_rec100;

always@(posedge clk or negedge rst_n)
begin
	if (rst_n == 1'b0)begin
		b_data_rec1 <= 4'd0;
		b_data_rec2 <= 4'd0;
		b_data_rec3 <= 4'd0;
		b_data_rec4 <= 4'd0;
		b_data_rec5 <= 4'd0;
		b_data_rec6 <= 4'd0;
		......
	    b_data_rec100 <= 4'd0;                             
	end            
	else if (resettime2_falling_flag == 1'b1)begin 
      if (bcodereadyflag == 1)begin   
         b_data_rec1 <= 4'd3;
         b_data_rec2 <= 4'd3;		
		end
		if(bcodebitcnt == 8'd3) b_data_rec3  <= bcodelevel;
		if(bcodebitcnt == 8'd4) b_data_rec4  <= bcodelevel;
		if(bcodebitcnt == 8'd5) b_data_rec5  <= bcodelevel;
		if(bcodebitcnt == 8'd6) b_data_rec6  <= bcodelevel;
		......	
        if(bcodebitcnt == 8'd100)b_data_rec50 <= bcodelevel; 
   end
end

   第四章:BUG

    编写程序的时候有很多不在控制之内得效果,其他只要这些bug能完整完成你需要的逻辑就行。就比如上面写的为什么置位成3,其实是有问题的,本来下面应该放入3的寄存器例,但是由于FPGA的执行逻辑问题,下次的下降沿才放入3的寄存器,所以不管怎么说,只要每个状态都能完成你需要的东西,就可以了。

    但是如果时间充足的话,还是最好没有bug。

    程序中还有一个bug,我现在还不知道在哪里,但是结果出来的不太对,所以明天得继续搞定这个东西,只有慢慢得来了,急不得!!!

最后:

    今天先写到锁存B码的值,其实下面就直接根据逻辑将锁存的100个值在bcodeflag变为1的那个周期内计算对应的utc时间即可。这段程序已经编写完毕,并且能够正确解析出B码的utc时间了。剩下的部分和验证部分明天再写!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值