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码解析分为两个部分: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的解析和输出。
- //保护10ms脉冲部分
-
- reg code10ms_en_d0;
- reg code10ms_en_d1;
- wire code10ms_rasing_flag;
- assign code10ms_rasing_flag = (~code10ms_en_d1) & code10ms_en_d0;
- always @(posedge clk or negedge rst_n) begin
- if (!rst_n) begin
- code10ms_en_d0 <= 1'b0;
- code10ms_en_d1 <= 1'b0;
- end
- else begin
- code10ms_en_d0 <= bcodein;
- code10ms_en_d1 <= code10ms_en_d0;
-
- end
- end
-
- reg code10ms_lag_en_d0;
- reg code10ms_lag_en_d1;
- wire code10ms_lag_falling_flag;
- wire code10ms_lag_rasing_flag;
- assign code10ms_lag_falling_flag = (~code10ms_lag_en_d0) & code10ms_lag_en_d1;
- assign code10ms_lag_rasing_flag = (~code10ms_lag_en_d1) & code10ms_lag_en_d0;
- always @(posedge clk or negedge rst_n) begin
- if (!rst_n) begin
- code10ms_lag_en_d0 <= 1'b0;
- code10ms_lag_en_d1 <= 1'b0;
- end
- else begin
- code10ms_lag_en_d0 <= code10ms_rasing_flag;
- code10ms_lag_en_d1 <= code10ms_lag_en_d0;
- end
- end
-
-
- (*noprune*)reg code10msflag;
- always@(posedge clk or negedge rst_n)
- begin
- if (rst_n == 1'b0)
- code10msflag <= 1'd0;
- else if (code10ms_lag_falling_flag == 1'b1)begin
- code10msflag <= 1'd1;
- end
- else if (code10ms_time_falling_flag == 1'b1)begin
- code10msflag <= 1'd0;
- end
- else if (code10ms_rasing_flag == 1'b1)begin
- code10msflag <= 1'd0;
- end
- end
-
- (*noprune*)reg [31:0] code10mstimer;
- always@(posedge clk or negedge rst_n)
- begin
- if (rst_n == 1'b0)
- code10mstimer <= 32'd0;
- else if (code10msflag == 1'b1)
- code10mstimer <= code10mstimer + 32'd1;
- else if (code10msflag == 1'b0)
- code10mstimer <= 32'd0;
- else if (code10ms_rasing_flag == 1'b1)
- code10mstimer <= 32'd0;
- end
-
- reg code10mslevel;
- always@(posedge clk or negedge rst_n)
- begin
- if (rst_n == 1'b0)
- code10mslevel <= 1'd0;
- else if (code10mstimer == 32'd525000) // 10.5ms 置高,11ms置低
- code10mslevel <= 1'b1;
- else if (code10mstimer == 32'd550000)
- code10mslevel <= 1'b0;
- end
-
- reg code10ms_time_en_d0;
- reg code10ms_time_en_d1;
- wire code10ms_time_falling_flag;
- wire code10ms_time_rasing_flag;
- assign code10ms_time_falling_flag = (~code10ms_time_en_d0) & code10ms_time_en_d1;
- assign code10ms_time_rasing_flag = (~code10ms_time_en_d1) & code10ms_time_en_d0;
- always @(posedge clk or negedge rst_n) begin
- if (!rst_n) begin
- code10ms_time_en_d0 <= 1'b0;
- code10ms_time_en_d1 <= 1'b0;
- end
- else begin
- code10ms_time_en_d0 <= code10mslevel;
- code10ms_time_en_d1 <= code10ms_time_en_d0;
- end
- end
代码比较简单,就不做逐行介绍了。
注意:这个代码结构非常重要,也就是前面介绍的自己命名的扫尾程序。架构:脉冲--定时器--标志位--脉冲--复位。
下面说下程序的大小:
主要程序占用1230+154+55= 1493个逻辑单元,其他的仿真波形之类的占用其他部分。如果缩减程序的话,可以达到1000左右。查询了FPGA的价格,估计得200块左右。但是不知道国产的FPGA的价格是多少,估计比这个高。看了下国产紫光同创的核心板,差不多得400左右。估计单纯的芯片的话,价格也差不多。需要国产化的小伙伴可以在现有程序的基础上减小相关代码,争取能用最低的配置完成B码的解析。
这篇文章介绍了程序的编写原则和基本架构,并且详细介绍了B码错误保护程序。下面的文章再详细的介绍B码的UTC解析和1PPS输出。需要代码的小伙伴可以看看哪篇文章可以关注公众号,因为新加的公众号图片都涉嫌违规。也可以直接搜索名字:电力电子嵌入式,看看能不能关注。到时候需要可以私信,我会把编写好的代码和工程放到百度网盘中,需要的小伙伴可以自己下载。