b码是100个字符于一帧内输入,我们需要做到拿到100个数据后,进行相对应的位置解析 本次我们是将b码的前60位解析成:年月日时分秒 所以我们对应的输入就是 b码一帧输入的数据, 输出为:年十位,年个位,日百位,日十位,日个位,时十位,时个位,分十位,分个位,秒十位,秒个位
自制参考图(网上有很多关于b码的表格和图片大家可以了解参考):

现在我们就来解析模块的编写:
我们想一想,当b码传数据进FPGA后,我们首先要做的就是消除亚稳态,也就是对b码进行打拍处理,让其在我们FPGA时钟下进行工作,以便我们接下来读取数据和解析数据。
消除亚稳态后,我们需要分辨b码中,那100个数据都是啥,然后咱就给解析成啥,就比如:b码中的P码元,就是高电平8ms,这个8ms也就是P码的标志。以此类推,b码中有3种数据分别是:2ms--0码元、5ms--1码元、8ms--P码元。我们知道这些后,便可将b码种不同的数据提取成1、0、P等进行解析。
我们观察可知,每个b码开始时,会有双P标志位,即:当双P产生时,我们开始进行解析,数据是准确的。所以我们拿到0、1、P后,接下来就是进行双P判断,当双P检测有效时,开始进行解析,即可把相对应的位置的信号,解析成我们的年月日时分秒。
具体代码如下:
//---------------------------------------------------------------------------------------
// 自己写b码解析
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
// b码是100个字符于一帧内输入,我们需要做到拿到100个数据后,进行相对应的位置解析
// 本次我们是将b码的前60位解析成:年月日时分秒
// 所以我们对应的输入就是 b码一帧输入的数据,
// 输出为:年十位,年个位,日百位,日十位,日个位,时十位,时个位,分十位,分个位,秒十位,秒个位
//---------------------------------------------------------------------------------------
module BMA_myself
(
input clk ,
input rst_n ,
input wire irig_b ,
output reg [ 3: 0] year_shi ,
output reg [ 3: 0] year_ge ,
output reg [ 1: 0] day_bai ,
output reg [ 3: 0] day_shi ,
output reg [ 3: 0] day_ge ,
output reg [ 1: 0] hour_shi ,
output reg [ 3: 0] hour_ge ,
output reg [ 2: 0] min_shi ,
output reg [ 3: 0] min_ge ,
output reg [ 2: 0] sec_shi ,
output reg [ 3: 0] sec_ge
);
//---------------------------------------------------------------------------------------
// 接收到b码信号后,先进行打两拍操作--目的为了消除亚稳态,使b码信号稳定
//---------------------------------------------------------------------------------------
reg irig_b_1 ;
reg irig_b_2 ;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
irig_b_1 <= 0;
irig_b_2 <= 0;
end
else
begin
irig_b_1 <= irig_b;
irig_b_2 <= irig_b_1;
end
end
//---------------------------------------------------------------------------------------
// b码稳定后,我们要得到一帧内一百个数据每个数据的长度(高电平计数器)--以便分别这个数据是2ms--5ms--8ms
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
// 经过一个数据后,我们生成1个下降沿,并且在此基础上打两拍,
// 目的是:当检测到第一个下降沿时,我们检测这个数据是否是2ms--5ms--8ms(0,1,P)
// 当检测到第二个下降沿时,此时我们的0.1.P已经解析出来了,比较即可
// 当检测到第三个下降沿时,我们将高电平时间计数器清零
//---------------------------------------------------------------------------------------
reg irig_b_fall ;//
reg irig_b_1_fall ;//
reg irig_b_2_fall ;//
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
irig_b_1_fall <= 0;
irig_b_2_fall <= 0;
end
else
begin
irig_b_fall <= (!irig_b_1&&irig_b_2);
irig_b_1_fall <= irig_b_fall;
irig_b_2_fall <= irig_b_1_fall;
end
end
//---------------------------------------------------------------------------------------
// 高电平计数器
//---------------------------------------------------------------------------------------
reg [ 18: 0] high_time_cnt ;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
high_time_cnt <= 'd0 ;
else if(irig_b_2_fall)
high_time_cnt <= 0 ;
else if(irig_b)
high_time_cnt <= high_time_cnt + 1'b1;
end
//---------------------------------------------------------------------------------------
// 拿到高电平计数器的值后,我们要对2ms--5ms--8ms进行区分(定义在模块名字处)
//---------------------------------------------------------------------------------------
parameter TIME_8MS = 399_999;
parameter TIME_5MS = 249_999;
parameter TIME_2MS = 99_999;
parameter TIME_1US = 49 ;
reg [ 1: 0] dec_b ;//码元判断
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
dec_b <= 'd0 ;
else if(( irig_b_fall )&&((high_time_cnt <= TIME_8MS+TIME_1US)&&(high_time_cnt >= TIME_8MS-TIME_1US)))
dec_b <= 2'b11 ; //P
else if(( irig_b_fall )&&((high_time_cnt <= TIME_5MS+TIME_1US)&&(high_time_cnt >= TIME_5MS-TIME_1US)))
dec_b <= 2'b01 ; //1
else if(( irig_b_fall )&&((high_time_cnt <= TIME_2MS+TIME_1US)&&(high_time_cnt >= TIME_2MS-TIME_1US)))
dec_b <= 2'b00 ; //0
end
//---------------------------------------------------------------------------------------
//把高电平计数转化为码元后,我们就可以根据表格进行相对应的赋值了,开始状态是PP,所以我们要进行双P检测
//---------------------------------------------------------------------------------------
reg [ 1: 0] dec_b_r ;//延迟一个码元---当双P时就能在同一时刻检测到两个P同时存在了
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
dec_b_r <= 0;
else if(irig_b_fall)
dec_b_r <= dec_b;
end
//---------------------------------------------------------------------------------------
//双P检测,并且开始b码解析(解析时间只需要前60位即可)
//---------------------------------------------------------------------------------------
reg start ;
reg [ 7: 0] b_num ;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
start <= 0;
else if(b_num == 'd60 && irig_b_fall)
start <= 0;
else if(irig_b_2_fall && dec_b == 2'b11 && dec_b_r == 2'b11)
start <= 1;
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
b_num <= 'd0 ;
else if(!start)
b_num <= 0 ;
else if(irig_b_fall&&start)
b_num <= b_num + 1'b1;
end
//---------------------------------------------------------------------------------------
// 秒个位
//---------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
sec_ge <= 4'b0000;
else if(irig_b_2_fall && b_num >= 'd1 && b_num <= 'd4)
sec_ge <= {dec_b[0],sec_ge[3:1]};
end
//---------------------------------------------------------------------------------------
// 秒十位
//---------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
sec_shi <= 3'b000;
else if(irig_b_2_fall && b_num >= 'd6 && b_num <= 'd8)
sec_shi <= {dec_b[0],sec_shi[2:1]};
end
//---------------------------------------------------------------------------------------
// 分个位
//---------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
min_ge <= 4'b0000;
else if(irig_b_2_fall && b_num >= 'd10 && b_num <= 'd13)
min_ge <= {dec_b[0],min_ge[3:1]};
end
//---------------------------------------------------------------------------------------
// 分十位
//---------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
min_shi <= 3'b000;
else if(irig_b_2_fall && b_num >= 'd15 && b_num <= 'd17)
min_shi <= {dec_b[0],min_shi[2:1]};
end
//---------------------------------------------------------------------------------------
// 时个位
//---------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
hour_ge <= 4'b0000;
else if(irig_b_2_fall && b_num >= 'd20 && b_num <= 'd23)
hour_ge <= {dec_b[0],hour_ge[3:1]};
end
//---------------------------------------------------------------------------------------
// 时十位
//---------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
hour_shi <= 2'b00;
else if(irig_b_2_fall && b_num >= 'd25 && b_num <= 'd26)
hour_shi <= {dec_b[0],hour_shi[1]};
end
//---------------------------------------------------------------------------------------
// 天个位
//---------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
day_ge <= 4'b0000;
else if(irig_b_2_fall && b_num >= 'd30 && b_num <= 'd33)
day_ge <= {dec_b[0],day_ge[3:1]};
end
//---------------------------------------------------------------------------------------
// 天十位
//---------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
day_shi <= 4'b0000;
else if(irig_b_2_fall && b_num >= 'd35 && b_num <= 'd38)
day_shi <= {dec_b[0],day_shi[3:1]};
end
//---------------------------------------------------------------------------------------
// 天百位
//---------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
day_bai <= 2'b00;
else if(irig_b_2_fall && b_num >= 'd40 && b_num <= 'd41)
day_bai <= {dec_b[0],day_bai[1]};
end
//---------------------------------------------------------------------------------------
// 年个位
//---------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
year_ge <= 4'b0000;
else if(irig_b_2_fall && b_num >= 'd50 && b_num <= 'd53)
year_ge <= {dec_b[0],year_ge[3:1]};
end
//---------------------------------------------------------------------------------------
// 年十位
//---------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
year_shi <= 4'b0000;
else if(irig_b_2_fall && b_num >= 'd55 && b_num <= 'd58)
year_shi <= {dec_b[0],year_shi[3:1]};
end
endmodule
我觉得代码写的已经很详细了,如有疑问请在评论区留言。
明天编写b码的仿真部分代码,以及代码仿真图。
2149

被折叠的 条评论
为什么被折叠?



