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的解析和输出。

//保护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输出。需要代码的小伙伴可以看看哪篇文章可以关注公众号,因为新加的公众号图片都涉嫌违规。也可以直接搜索名字:电力电子嵌入式,看看能不能关注。到时候需要可以私信,我会把编写好的代码和工程放到百度网盘中,需要的小伙伴可以自己下载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值