• FPGA解析B码----连载4


    前言

        昨天已经写完将100个数据锁存到对应寄存器里面,下面就是解B码的过程。

    第一章:计算UTC时间

    1. (*noprune*)reg [7:0] utc_sec;
    2. (*noprune*)reg [7:0] utc_min;
    3. (*noprune*)reg [7:0] utc_hou;
    4. (*noprune*)reg [9:0] utc_day;
    5. (*noprune*)reg [7:0] utc_yea;
    6. always@(posedge clk or negedge rst_n)
    7. begin
    8. if (rst_n == 1'b0)begin
    9. utc_sec <= 8'd0;
    10. utc_min <= 8'd0;
    11. utc_hou <= 8'd0;
    12. utc_day <= 10'd0;
    13. utc_yea <= 8'd0;
    14. end
    15. else if (bcodeflag == 1'b1)begin
    16. if(b_data_rec3 >= 4'd1)utc_sec[0] <= 1'b0;
    17. if(b_data_rec3 >= 4'd2)utc_sec[0] <= 1'b1;
    18. if(b_data_rec4 >= 4'd1)utc_sec[1] <= 1'b0;
    19. if(b_data_rec4 >= 4'd2)utc_sec[1] <= 1'b1;
    20. if(b_data_rec5 >= 4'd1)utc_sec[2] <= 1'b0;
    21. if(b_data_rec5 >= 4'd2)utc_sec[2] <= 1'b1;
    22. if(b_data_rec6 >= 4'd1)utc_sec[3] <= 1'b0;
    23. if(b_data_rec6 >= 4'd2)utc_sec[3] <= 1'b1;
    24. if(b_data_rec8 >= 4'd1)utc_sec[4] <= 1'b0;
    25. if(b_data_rec8 >= 4'd2)utc_sec[4] <= 1'b1;
    26. if(b_data_rec9 >= 4'd1)utc_sec[5] <= 1'b0;
    27. if(b_data_rec9 >= 4'd2)utc_sec[5] <= 1'b1;
    28. if(b_data_rec10 >= 4'd1)utc_sec[6] <= 1'b0;
    29. if(b_data_rec10 >= 4'd2)utc_sec[6] <= 1'b1;
    30. if(b_data_rec12 >= 4'd1)utc_min[0] <= 1'b0;
    31. if(b_data_rec12 >= 4'd2)utc_min[0] <= 1'b1;
    32. if(b_data_rec13 >= 4'd1)utc_min[1] <= 1'b0;
    33. if(b_data_rec13 >= 4'd2)utc_min[1] <= 1'b1;
    34. if(b_data_rec14 >= 4'd1)utc_min[2] <= 1'b0;
    35. if(b_data_rec14 >= 4'd2)utc_min[2] <= 1'b1;
    36. if(b_data_rec15 >= 4'd1)utc_min[3] <= 1'b0;
    37. if(b_data_rec15 >= 4'd2)utc_min[3] <= 1'b1;
    38. if(b_data_rec17 >= 4'd1)utc_min[4] <= 1'b0;
    39. if(b_data_rec17 >= 4'd2)utc_min[4] <= 1'b1;
    40. if(b_data_rec18 >= 4'd1)utc_min[5] <= 1'b0;
    41. if(b_data_rec18 >= 4'd2)utc_min[5] <= 1'b1;
    42. if(b_data_rec19 >= 4'd1)utc_min[6] <= 1'b0;
    43. if(b_data_rec19 >= 4'd2)utc_min[6] <= 1'b1;
    44. if(b_data_rec20 >= 4'd1)utc_min[7] <= 1'b0;
    45. if(b_data_rec20 >= 4'd2)utc_min[7] <= 1'b1;
    46. if(b_data_rec22 >= 4'd1)utc_hou[0] <= 1'b0;
    47. if(b_data_rec22 >= 4'd2)utc_hou[0] <= 1'b1;
    48. if(b_data_rec23 >= 4'd1)utc_hou[1] <= 1'b0;
    49. if(b_data_rec23 >= 4'd2)utc_hou[1] <= 1'b1;
    50. if(b_data_rec24 >= 4'd1)utc_hou[2] <= 1'b0;
    51. if(b_data_rec24 >= 4'd2)utc_hou[2] <= 1'b1;
    52. if(b_data_rec25 >= 4'd1)utc_hou[3] <= 1'b0;
    53. if(b_data_rec25 >= 4'd2)utc_hou[3] <= 1'b1;
    54. if(b_data_rec27 >= 4'd1)utc_hou[4] <= 1'b0;
    55. if(b_data_rec27 >= 4'd2)utc_hou[4] <= 1'b1;
    56. if(b_data_rec28 >= 4'd1)utc_hou[5] <= 1'b0;
    57. if(b_data_rec28 >= 4'd2)utc_hou[5] <= 1'b1;
    58. if(b_data_rec29 >= 4'd1)utc_hou[6] <= 1'b0;
    59. if(b_data_rec29 >= 4'd2)utc_hou[6] <= 1'b1;
    60. if(b_data_rec30 >= 4'd1)utc_hou[7] <= 1'b0;
    61. if(b_data_rec30 >= 4'd2)utc_hou[7] <= 1'b1;
    62. if(b_data_rec32 >= 4'd1)utc_day[0] <= 1'b0;
    63. if(b_data_rec32 >= 4'd2)utc_day[0] <= 1'b1;
    64. if(b_data_rec33 >= 4'd1)utc_day[1] <= 1'b0;
    65. if(b_data_rec33 >= 4'd2)utc_day[1] <= 1'b1;
    66. if(b_data_rec34 >= 4'd1)utc_day[2] <= 1'b0;
    67. if(b_data_rec34 >= 4'd2)utc_day[2] <= 1'b1;
    68. if(b_data_rec35 >= 4'd1)utc_day[3] <= 1'b0;
    69. if(b_data_rec35 >= 4'd2)utc_day[3] <= 1'b1;
    70. if(b_data_rec37 >= 4'd1)utc_day[4] <= 1'b0;
    71. if(b_data_rec37 >= 4'd2)utc_day[4] <= 1'b1;
    72. if(b_data_rec38 >= 4'd1)utc_day[5] <= 1'b0;
    73. if(b_data_rec38 >= 4'd2)utc_day[5] <= 1'b1;
    74. if(b_data_rec39 >= 4'd1)utc_day[6] <= 1'b0;
    75. if(b_data_rec39 >= 4'd2)utc_day[6] <= 1'b1;
    76. if(b_data_rec40 >= 4'd1)utc_day[7] <= 1'b0;
    77. if(b_data_rec40 >= 4'd2)utc_day[7] <= 1'b1;
    78. if(b_data_rec42 >= 4'd1)utc_day[8] <= 1'b0;
    79. if(b_data_rec42 >= 4'd2)utc_day[8] <= 1'b1;
    80. if(b_data_rec43 >= 4'd1)utc_day[9] <= 1'b0;
    81. if(b_data_rec43 >= 4'd2)utc_day[9] <= 1'b1;
    82. if(b_data_rec52 >= 4'd1)utc_yea[0] <= 1'b0;
    83. if(b_data_rec52 >= 4'd2)utc_yea[0] <= 1'b1;
    84. if(b_data_rec53 >= 4'd1)utc_yea[1] <= 1'b0;
    85. if(b_data_rec53 >= 4'd2)utc_yea[1] <= 1'b1;
    86. if(b_data_rec54 >= 4'd1)utc_yea[2] <= 1'b0;
    87. if(b_data_rec54 >= 4'd2)utc_yea[2] <= 1'b1;
    88. if(b_data_rec55 >= 4'd1)utc_yea[3] <= 1'b0;
    89. if(b_data_rec55 >= 4'd2)utc_yea[3] <= 1'b1;
    90. if(b_data_rec57 >= 4'd1)utc_yea[4] <= 1'b0;
    91. if(b_data_rec57 >= 4'd2)utc_yea[4] <= 1'b1;
    92. if(b_data_rec58 >= 4'd1)utc_yea[5] <= 1'b0;
    93. if(b_data_rec58 >= 4'd2)utc_yea[5] <= 1'b1;
    94. if(b_data_rec59 >= 4'd1)utc_yea[6] <= 1'b0;
    95. if(b_data_rec59 >= 4'd2)utc_yea[6] <= 1'b1;
    96. if(b_data_rec60 >= 4'd1)utc_yea[7] <= 1'b0;
    97. if(b_data_rec60 >= 4'd2)utc_yea[7] <= 1'b1;
    98. end
    99. end

        前面锁存的信号为3,2,1和0信号,3代表P标志位,2代表高电平,1代表低电平。所以先将锁存器的值转化为01信号,判断完毕后,进行计算。

        注意:这里用的脉冲信号为bcodeflag,这个信号在采集到101个点的时候计算,并且没有时间卡点。因为B码的最后一位是不代表信息的,所以这个就不用过多考虑锁存不锁存的问题,所有的B码都是前面99个里面。

    1. reg resettime3_en_d0;
    2. reg resettime3_en_d1;
    3. wire resettime3_falling_flag;
    4. wire resettime3_rasing_flag;
    5. assign resettime3_falling_flag = (~resettime3_en_d0) & resettime3_en_d1;
    6. assign resettime3_rasing_flag = (~resettime3_en_d1) & resettime3_en_d0;
    7. always @(posedge clk or negedge rst_n) begin
    8. if (!rst_n) begin
    9. resettime3_en_d0 <= 1'b0;
    10. resettime3_en_d1 <= 1'b0;
    11. end
    12. else begin
    13. resettime3_en_d0 <= bcodeflag;
    14. resettime3_en_d1 <= resettime3_en_d0;
    15. end
    16. end

        在bcodeflag的下降沿之后顺延一个周期,即判断完01之后,进行计算。

    1. (*noprune*)reg [31:0] utc_SecondData;
    2. (*noprune*)reg [31:0] utc_MinuteData;
    3. (*noprune*)reg [31:0] utc_HourData;
    4. (*noprune*)reg [31:0] utc_DayData;
    5. (*noprune*)reg [31:0] utc_YearData;
    6. always@(posedge clk or negedge rst_n)
    7. begin
    8. if (rst_n == 1'b0)
    9. utc_SecondData <= 32'd0;
    10. else if (resettime3_falling_flag == 1'b1)begin
    11. utc_SecondData = utc_sec[0] + 2*utc_sec[1] + 4*utc_sec[2] + 8*utc_sec[3]
    12. +(utc_sec[4] + 2*utc_sec[5] + 4*utc_sec[6])*10;
    13. utc_MinuteData = utc_min[0] + 2*utc_min[1] + 4*utc_min[2] + 8*utc_min[3]
    14. +(utc_min[4] + 2*utc_min[5] + 4*utc_min[6] + 8*utc_min[7])*10;
    15. utc_HourData = utc_hou[0] + 2*utc_hou[1] + 4*utc_hou[2] + 8*utc_hou[3]
    16. +(utc_hou[4] + 2*utc_hou[5] + 4*utc_hou[6] + 8*utc_hou[7])*10;
    17. utc_DayData = utc_day[0] + 2*utc_day[1] + 4*utc_day[2] + 8*utc_day[3]
    18. +(utc_day[4] + 2*utc_day[5] + 4*utc_day[6] + 8*utc_day[7])*10
    19. +(utc_day[8] + 2*utc_day[9])*100;
    20. utc_YearData = utc_yea[0] + 2*utc_yea[1] + 4*utc_yea[2] + 8*utc_yea[3]
    21. +(utc_yea[4] + 2*utc_yea[5] + 4*utc_yea[6] + 8*utc_yea[7])*10;
    22. end
    23. end

        这样在最后一个脉宽的时候计算出对应的utc时间。

    第二章:波形验证

         接入B码后可以看出,cnt到100,然后变为101,但是在锁存之前变为0。之后再resetime3之后的下降沿,B码的秒时间可以看出是31s,而其他时间为14点28,而年对应为22,即2022年,验证后,天数为216天,即2022年8月4日。当然这仅仅验证了UTC时间的解码,其他的关键信息还没有提取出来。应该可以用同样的方法可以将其他信息放到一个寄存器中。

    第三章:存在的BUG

    1. always@(posedge clk or negedge rst_n)
    2. begin
    3. if (rst_n == 1'b0)
    4. bcodebitcnt <= 8'd0;
    5. else if (bpluse_falling_flag == 1)
    6. bcodebitcnt <= bcodebitcnt + 1'b1;
    7. else if (bcodereadyflag == 1)
    8. bcodebitcnt <= 8'd3;
    9. else if (bcodebitcnt == 8'd101)
    10. bcodebitcnt <= 0;
    11. else
    12. bcodebitcnt <= bcodebitcnt;
    13. end
    14. always@(posedge clk or negedge rst_n)
    15. begin
    16. if (rst_n == 1'b0)
    17. bcodeflag <= 1'd0;
    18. else if (bpluse_falling_flag == 1)
    19. bcodeflag <= 1'd0;
    20. else if (bcodebitcnt == 8'd101)
    21. bcodeflag <= 1'd1;
    22. else
    23. bcodeflag <= 1'd0;
    24. end

        这段代码输出两个量,一个是cnt,也就是没有锁存时,在B码的下降沿时,从0到100,锁存之后从3到100。另一个是bcodeflag,当下降沿来时等于0,当cnt等于101时变为1。这个地方问题就是没有锁存两个B码的P标志时,cnt也会变为101,这样bcodeflag也会变为1,也即utc时间也会计算,这个就比较麻烦了。

    第四章:1PPS怎么输出

        1PPS的上升沿和2个P标志中的第二个脉宽上升沿重合,这样必须判断出来两个P帧之后,在下一个1s中的时候,第2个B码的脉宽的上升沿处输出脉冲。现在考虑两种方案:

        (1)方案1:判断2个P标志之后,定时器开启,在995ms的时候输出1个flag,然后1005ms时输出0flag,然后将B码信号与这个flag与一下,那样输出的脉冲即为1PPS的上升沿。

        (2)方案2:判断2个P标志之后,在1sB码的之后的下一个1s的第一个P标志之后,输出1个flag,然后输出一定宽度的flag,然后将B码信号与这个flag与一下,也可以输出对应的1PPS脉冲的上升沿。

        先不考虑其他传递参数,仅仅考虑utc时间的话,在600ms左右能解出具体的utc时间,所以在下一个1pps之前,做好准备是没什么问题。

        出现以下问题需要解决:

        (1)B码在2个P标志位之后信号出现问题,B码在中间消失,之后B码继续出现。

        (2)B码在2个P标志位之后信号出现问题,B码间隔固定时间,即之后的P帧刚好对上,B码再次出现。

        所以感觉能锁存到2个P帧是关键,之后无论B码怎么消失,只要在下一个2个P帧到来时,给定高电平与B码与就行,所以选择第1个方案比较稳妥。

        至于B码消失,utc时间怎么解,这个需要再次考虑。

        所以按照第一个方案的思路解决1PPS的输出问题。

  • 相关阅读:
    企业数字化转型的先锋利器——低代码快速开发平台
    随机过程:布朗运动
    人机智能的逻辑哲学论
    ZYNQ:串口-CAN协议转换
    千万并发连接下,如何保障网络性能
    Spring面试题21:说一说Spring的@Required注解和@Qualifier注解
    Redis GEO 类型与 API 结合,地理位置优化的绝佳实践
    STM32内部flash闪存的总结
    前端面试谈:简历通用注意事项
    单链表oj (上),详细的过程分析,每道题有多种解题思路,一定会有所收获
  • 原文地址:https://blog.csdn.net/weixin_45426095/article/details/126158212