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


    前言

        现有:STM32已经编写好B码解析程序,现需要采用FPGA解析B码。

        原因:CSDN上找不到编写的B码程序,就算有全部需要下载,穷,没有下载点。

        区别:STM32是顺序执行,方便接收B码和解析B码,同时有PWM采集例程,定时器,计数器。

        难点:FPGA是并行结构,逻辑比较复杂。

    写在前面

        之前使用FPGA仅仅是编写了串口,SPI,double双精度数据的运算。对于1s数据和脉宽采集这种还没有编写过,现在尝试采用自己总结的编写方式和规范一步一步的编写B码解析程序。

        写这篇文章的时候,自己还不知道怎么去编写,下面一步一步的将自己的思维方式和程序展示,希望能对学习FPGA的小伙伴和解析B码的小伙伴给与帮助,能节省一定的时间和金钱。也希望能和大家一起学习。

    第一章:需求

        输入:B码;

        输出:1PPS信号,UTC时间,B码关键帧信息。

    第二章:B码结构

         信号时长:1s;

         信号种类:2ms:0电平(暗红色);5ms:1电平(橙黄色);8ms:标志电平(绿色);

    第三章:拆解

        大类拆解:1PPS,B码信息输出;

        小类拆解:脉宽采集,码元存储,时间计算,串口输出。

    第四章:显示部分

        这部分最好加上,显示自己的程序正在运行,最好用1个LED灯进行显示,然后最后程序定型之后再给去掉,如果空间大的话那就随意了。

    1. always@(posedge clk or negedge rst_n)
    2. begin
    3. if (rst_n == 1'b0)
    4. timer <= 32'd0;
    5. else if (timer == 32'd9_999_999)
    6. timer <= 32'd0;
    7. else
    8. timer <= timer + 32'd1;
    9. end

            先来个计数器,一般程序就采用这种格式(这个格式是自己总结的,方便,好看,简单,一句一句的来,以后自己阅读着也能看出来自己写的是啥!)

        (1)复位,变量赋值为0;

        (2)条件1,变量处理1;

        (3)条件2,变量处理2;

        (4)其他条件,变量处理3。

        当然中间也可以再增加其他条件。计数器作用从0加到9999999,然后再回到0。具体最大值多少随便。

        然后再来个点灯,到一定数值,flag加1,然后下次再加1,也就是flag在0和1之间变化。

    1. always@(posedge clk or negedge rst_n)
    2. begin
    3. if (rst_n == 1'b0)
    4. flag <= 1'b0;
    5. else if(timer == 32'd8_999_999)
    6. flag <= flag + 1'b1;
    7. else
    8. flag <= flag;
    9. end
    10. always@(posedge clk or negedge rst_n)
    11. begin
    12. if(rst_n == 1'b0)
    13. begin
    14. led4<=1'b1;
    15. end
    16. else begin
    17. case (flag)
    18. 1'b0 : led4<=1'b1;
    19. 1'b1 : led4<=1'b0;
    20. default : led4<=1'b0;
    21. endcase
    22. end
    23. end

        结构还是刚才那个结构,复位置0,time的值等于8999999时flag加1,其他条件flag不变。

        复位灯置0,两个条件下LED分别置0和1,代表亮和灭。

        这样LED灯就可以按照一定周期亮和灭了。

    第五章:脉宽采集

        思路:这部分我想着大概分成4部分,具体还需要怎么弄,一会编程看看!

        (1)上升沿检测;(2)下降沿检测;(3)沿检测后的计数器启动和停止;(4)脉宽时间计算。

        上升沿检测和下降沿检测程序:

    1. //脉宽的上升沿和下降沿检测
    2. reg bpluse_en_d0;
    3. reg bpluse_en_d1;
    4. wire bpluse_falling_flag;
    5. wire bpluse_rasing_flag;
    6. assign bpluse_falling_flag = (~bpluse_en_d0) & bpluse_en_d1;
    7. assign bpluse_rasing_flag = (~bpluse_en_d1) & bpluse_en_d0;
    8. always @(posedge clk or negedge rst_n) begin
    9. if (!rst_n) begin
    10. bpluse_en_d0 <= 1'b0;
    11. bpluse_en_d1 <= 1'b0;
    12. end
    13. else begin
    14. bpluse_en_d0 <= bcodein;
    15. bpluse_en_d1 <= bpluse_en_d0;
    16. end
    17. end

        检测到上升沿和下降沿时,两个flag分别一个周期的脉冲信号。

    1. //置位time是否开启
    2. reg timebeginflag;
    3. always@(posedge clk or negedge rst_n)
    4. begin
    5. if (rst_n == 1'b0)
    6. timebeginflag <= 1'd0;
    7. else if (bpluse_rasing_flag == 1)
    8. timebeginflag <= 1'd1;
    9. else if (bpluse_falling_flag == 1)
    10. timebeginflag <= 1'd0;
    11. else
    12. timebeginflag <= 1'd0;
    13. end

        当上升沿和下降沿时,timebeginflag分别置1和0。

    1. //上升沿之后计数器工作,下降沿之后计数器停止
    2. reg [31:0] timer;
    3. always@(posedge clk or negedge rst_n)
    4. begin
    5. if (rst_n == 1'b0)
    6. timer <= 32'd0;
    7. else if (timebeginflag == 1)
    8. timer <= timer + 32'd1;
    9. else if (timebeginflag == 0)
    10. timer <= timer;
    11. end

        上升沿时,time计数器开始计数,下降沿时,time计数器停止。

        这块缺少一个time复位为0的一个条件,这个条件为time计数器中的数据取出后的标志位,当取出time之后,time复位,为下次的脉宽测量做准备。

        脉宽计算程序:

    1. reg bcodelevel;
    2. always@(posedge clk or negedge rst_n)
    3. begin
    4. if (rst_n == 1'b0)
    5. bcodelevel <= 0;
    6. else if (bpluse_falling_flag == 1)begin
    7. if(timer >= 350000)bcodelevel = 3; //P电平
    8. else if(timer >= 200000)bcodelevel = 2; //1电平
    9. else if(timer >= 50000 )bcodelevel = 1; //0电平
    10. else bcodelevel = 0;
    11. end
    12. else
    13. bcodelevel <= 0;
    14. end

        当下降沿来时,time计数器停止计数,同时判断time中的数据,由于time的数据不那么准确,可以判断大范围之后的电平,大于7ms即为标志电平,大于4ms即为1电平,大于1ms即为0电平。中间用了else,所以3个判断并不冲突。这样就能判断每个脉冲的电平了。

    第六章:测试

        程序先编写到此,明天测试编写程序。测试程序直接发送对应的ms数的电平信号,测试能否采集到对应电平。

        整体思路就是先采集上升沿和下降沿,启动计数器,下降沿时判断计数器数据大小,根据数据大小输出电平类型。当然下面还得锁存电平,只能明天考虑了

  • 相关阅读:
    spring boot + minio 8.5.4 遇到 okhttp3包冲突
    编程之美4 Nim游戏
    携手ChainGPT 人工智能基础设施 波场TRON革新 Web3 版图
    LVS负载均衡及LVS-NAT模式
    《C和指针》笔记33:指针数组
    js基础笔记学习196-字符串得方法2
    干了三年外包。。。忘了什么是CICD。。。
    亚马逊云科技,引领生成式AI的新时代
    Python 教程之控制流(12)组合迭代器
    C++11补充:智能指针如std::unique_ptr如何添加自定义的deleter
  • 原文地址:https://blog.csdn.net/weixin_45426095/article/details/126010009