• FPGA解析B码----连载6(完结篇)


    前言

        7月25号到现在的20天时间里,B码的FPGA解析程序编写完毕,并且能用正确串口输出UTC时间、B码的关键信息和1PPS输出。差不多按照FPGA的编写规则和之前的while(1)思维方式。编写下来发现之前的STM32程序中间存在很严重的BUG,所以采用并行思维编程还是很有好处的。希望小伙伴能感悟下并行思维方式,并进一步提高串行的while(1)编程逻辑思维方式水平。

    编写原因

        (1)网上找不到现成的FPGA的B码解析程序,就算有也需要各种币,自己比较穷。

        (2)别人的程序总归要消化吸收,读明白别人的程序。这步仅仅有程序的话比较麻烦,不知道别人的逻辑思维方式,所以还不如自己按照自己的方法去编写程序。

        (3)给需要B码的小伙伴一些帮助,能免一些重复造轮子。

    第一章:编写原则

        (1)用最简单的方式编程,一个模块一个变量。别人能看懂,将来自己也能看懂;

        (2)每个输出变量互不干扰,符合FPGA的编程规则和优势;

        (3)变量输出时间上互不干扰,符合程序最基本的规则,将错误控制在一定时间内。

    第二章:顶层配置

        顶层配置采用最简单的方式,包含三个部分:B码解析,串口输出,LED指示。

         LED指示部分作用:指示程序在正常运行,这个最好加上,知道程序在跑;

        B码解析和串口输出模块分开,串口部分网上介绍的非常详细,不再赘述。关注点主要在B码解析。

    第三章:B码解析分类

        B码解析分为两个部分:UTC时间解析(包含除时间的B码关键信息),1PPS产生。

        程序分为三个部分:UTC时间解析,1PPS产生,B码错误保护程序。

        前面两个部分在前面的文章中已经做了大致的介绍,最近两天主要在编写B码错误保护程序,这部分很重要。编写原则:可不输出,但是不能输出错误信息。

        下面一部分一部分介绍各个部分的逻辑和代码。

    第四章:保护程序

        程序原则:一个B码单元(10ms)保护不影响下一个B码的单元保护,并且整体上加以保护。即1s内丢失任意一个B码单元不输出utc时间和1pps信号。

        保护程序分为三个部分:起始复位,上升沿启动,过时保护;

        起始复位:B码的上升沿时,flag置0,time置0,为启动做准备;

        上升沿启动:B码的上升沿延后上升沿,flag置1,time启动。如果10ms之后,再有B码上升沿到来,则再进去起始复位,两个量再置0。如果10ms后没有B码上升沿到来,则进入过时保护部分。

        过时保护:time到10.5ms时,level置1,再计时到11ms时,确定B码上升沿缺失,则level置0。其下降沿时,flag置0,同时time置0。这样形成三个变量的闭环:flag,time,level。

        10.5ms和11ms这两个变量应该变得更近才好,但是应该没啥问题。

        保护程序主要输出11ms后的falling_flag,这个是最终的目的。如果有这个下降沿置1,则停止UTC时间的解析和输出、1PPS的解析和输出。

    1. //保护10ms脉冲部分
    2. reg code10ms_en_d0;
    3. reg code10ms_en_d1;
    4. wire code10ms_rasing_flag;
    5. assign code10ms_rasing_flag = (~code10ms_en_d1) & code10ms_en_d0;
    6. always @(posedge clk or negedge rst_n) begin
    7. if (!rst_n) begin
    8. code10ms_en_d0 <= 1'b0;
    9. code10ms_en_d1 <= 1'b0;
    10. end
    11. else begin
    12. code10ms_en_d0 <= bcodein;
    13. code10ms_en_d1 <= code10ms_en_d0;
    14. end
    15. end
    16. reg code10ms_lag_en_d0;
    17. reg code10ms_lag_en_d1;
    18. wire code10ms_lag_falling_flag;
    19. wire code10ms_lag_rasing_flag;
    20. assign code10ms_lag_falling_flag = (~code10ms_lag_en_d0) & code10ms_lag_en_d1;
    21. assign code10ms_lag_rasing_flag = (~code10ms_lag_en_d1) & code10ms_lag_en_d0;
    22. always @(posedge clk or negedge rst_n) begin
    23. if (!rst_n) begin
    24. code10ms_lag_en_d0 <= 1'b0;
    25. code10ms_lag_en_d1 <= 1'b0;
    26. end
    27. else begin
    28. code10ms_lag_en_d0 <= code10ms_rasing_flag;
    29. code10ms_lag_en_d1 <= code10ms_lag_en_d0;
    30. end
    31. end
    32. (*noprune*)reg code10msflag;
    33. always@(posedge clk or negedge rst_n)
    34. begin
    35. if (rst_n == 1'b0)
    36. code10msflag <= 1'd0;
    37. else if (code10ms_lag_falling_flag == 1'b1)begin
    38. code10msflag <= 1'd1;
    39. end
    40. else if (code10ms_time_falling_flag == 1'b1)begin
    41. code10msflag <= 1'd0;
    42. end
    43. else if (code10ms_rasing_flag == 1'b1)begin
    44. code10msflag <= 1'd0;
    45. end
    46. end
    47. (*noprune*)reg [31:0] code10mstimer;
    48. always@(posedge clk or negedge rst_n)
    49. begin
    50. if (rst_n == 1'b0)
    51. code10mstimer <= 32'd0;
    52. else if (code10msflag == 1'b1)
    53. code10mstimer <= code10mstimer + 32'd1;
    54. else if (code10msflag == 1'b0)
    55. code10mstimer <= 32'd0;
    56. else if (code10ms_rasing_flag == 1'b1)
    57. code10mstimer <= 32'd0;
    58. end
    59. reg code10mslevel;
    60. always@(posedge clk or negedge rst_n)
    61. begin
    62. if (rst_n == 1'b0)
    63. code10mslevel <= 1'd0;
    64. else if (code10mstimer == 32'd525000) // 10.5ms 置高,11ms置低
    65. code10mslevel <= 1'b1;
    66. else if (code10mstimer == 32'd550000)
    67. code10mslevel <= 1'b0;
    68. end
    69. reg code10ms_time_en_d0;
    70. reg code10ms_time_en_d1;
    71. wire code10ms_time_falling_flag;
    72. wire code10ms_time_rasing_flag;
    73. assign code10ms_time_falling_flag = (~code10ms_time_en_d0) & code10ms_time_en_d1;
    74. assign code10ms_time_rasing_flag = (~code10ms_time_en_d1) & code10ms_time_en_d0;
    75. always @(posedge clk or negedge rst_n) begin
    76. if (!rst_n) begin
    77. code10ms_time_en_d0 <= 1'b0;
    78. code10ms_time_en_d1 <= 1'b0;
    79. end
    80. else begin
    81. code10ms_time_en_d0 <= code10mslevel;
    82. code10ms_time_en_d1 <= code10ms_time_en_d0;
    83. end
    84. end

        代码比较简单,就不做逐行介绍了。

        注意:这个代码结构非常重要,也就是前面介绍的自己命名的扫尾程序。架构:脉冲--定时器--标志位--脉冲--复位。

    第五部分:程序大小

        下面说下程序的大小:

        主要程序占用1230+154+55= 1493个逻辑单元,其他的仿真波形之类的占用其他部分。如果缩减程序的话,可以达到1000左右。查询了FPGA的价格,估计得200块左右。但是不知道国产的FPGA的价格是多少,估计比这个高。看了下国产紫光同创的核心板,差不多得400左右。估计单纯的芯片的话,价格也差不多。需要国产化的小伙伴可以在现有程序的基础上减小相关代码,争取能用最低的配置完成B码的解析。

    第六部分:展望

        这篇文章介绍了程序的编写原则和基本架构,并且详细介绍了B码错误保护程序。下面的文章再详细的介绍B码的UTC解析和1PPS输出。需要代码的小伙伴可以看看哪篇文章可以关注公众号,因为新加的公众号图片都涉嫌违规。也可以直接搜索名字:电力电子嵌入式,看看能不能关注。到时候需要可以私信,我会把编写好的代码和工程放到百度网盘中,需要的小伙伴可以自己下载。

  • 相关阅读:
    情绪感受一点分享
    XAMPP、Apache搭建本地PHP服务器(全网最保姆级)
    JVM-内存管理
    【GPU】Nvidia CUDA 编程高级教程——利用蒙特卡罗法求解 的近似值
    浏览器跨域问题
    Alkyne-PEG-CHO,炔基PEG醛基
    23种设计模式(十八)迭代器模式(阁瑞钛伦特软件-九耶实训)
    Linux认识与学习BASH
    Android简易音乐重构MVVM Java版-使用Navigation导航组件重构主界面及其他页面跳转(二十)
    java常用集合及常用类
  • 原文地址:https://blog.csdn.net/weixin_45426095/article/details/126380847