目录
一、背景介绍
二、串行时间码
三、B码介绍
四、B码解析模块的设计
绘制模块框图及波形图
编写模块代码
编写仿真代码
仿真验证
一、背景介绍
IRIG(Inter-Range Instrumentation Group 靶场仪器组)是美国RCC(Range Commanders Council靶场司令委员会)下属机构,成立于1951年8月,其常设机构在美国白沙导弹靶场。
它的执行委员会是由美国各靶场的代表,三军代表、国防部、国家航空航天局和国家标准局的代表组成。它的职责是负责靶场间的信息交换,制订标准、协调设备的研制和协调靶场间的相互配合。它所制定的IRIG标准,已成为国际上通用标准,在西欧、日本、澳大利亚等处得到了广泛的应用
IRIG是美国靶场仪器组的简称。IRIG时间标准有两大类:一类是并行时间码格式,这类码由于是并行格式,传输距离较近,且是二进制,因此远不如串行格式广泛;另一类是串行时间码,共有六种格式,即A、B、D、E、G、H。它们的主要差别是时间码的帧速率不同,IRIG-B即为其中的B型码。B型码的时帧速率为1帧/s;可传递100位的信息。作为应用广泛的时间码,B型码具用以下主要特点:携带信息量大,高分辨率;调制后的B码带宽,适用于远距离传输;分直流、交流两种;具有接口标准化,国际通用等特点。
二、串行时间码
IRIG时间码标准有二大类。一类是并行时间码格式,这类码由于是并行形式,传输距离较近,且是二进制,因此应用远不如串行格式广泛。另一类是串行时间码,共有六种格式。即IRIG—A、B、D、E、G、H。它们的主要差别是时间码的帧速率不同,从最慢的每小时一帧的D格式到最快的每十毫秒一帧的G格式。各种格式的主要参数如下表所述。
为了便于传递,可用标准正弦波载频进行幅度调制。标准正弦波载频的频率与码元速率严格相关。B码的标准正弦波载频频率为1KHz。同时,其正交过零点与所调制格式码元的前沿相符合,标准的调制比为10比3。调制后的B码通常称IRIG-B(AC)码,未经幅度调制的通常称IRIG-B(DC)码。
IRIG-B(DC)码的接口通常采用TTL接口和RS422(V.11)接口。IRIG-B(AC)码的接口采用平衡接口。IRIG-B(DC)码的同步精度可达几十纳秒量级,IRIG-B(AC)码的同步精度一般为10~20us(微秒)。

|
格 式 |
时帧周期 |
码元速率 |
二-十进制 信息位数 |
表示时间的信息 |
|
IRIG-D |
1小时 |
1个/分 |
16 |
天、时 |
|
IRIG-H |
1分 |
1个/秒 |
23 |
天、时、分 |
|
IRIG-E |
10秒 |
10个/秒 |
26 |
天、时、分、10秒 |
|
IRIG-B |
1秒 |
100个/秒 |
30 |
天、时、分、秒 |
|
IRIG-A |
0.1秒 |
1000个/秒 |
34 |
天、时、分、秒、0.1秒 |
|
IRIG-G |
0.01秒 |
10,000个/秒 |
38 |
天、时、分、秒、0.1秒,0.01秒 |
三、B码介绍
IRIG(Inter Range Instrumentation Group)起源于军队靶场的时间同步,靶场中的时间系统为卫星或航天器发射、常规武器试验、测控系统提供标准时间。IRIG-B时间码(简称B码)就是由IRIG所属的TCG(TelecommunicationGroup)制订的一种串行时间码,被广泛应用于时间信息传输系统中。在实际的应用中,根据距离B码发生器的远近及不同时间精度的要求,B码在实际传输中采用了两种码型AC码(交流码)和DC码(直流码)。当传输距离比较远时采用AC码,当传输距离近时则采用DC码。
在时间服务器、时统设备等时间传输设备中需要非常准确的时间同步,从而保证数据传输的准确性。在数据传输技术的要求高的系统中,如果不采用时钟同步技术,极有可能造成各个级联设备数据时间上的细微误差,进而造成数据传递结果的不准确,将对数据的研究处理产生严重的影响。时间、频率统一设备是为其他设备提供标准、统一时间的,是其他一切时间服务的基础,因此,时统设备是各科学研究领域研究的重要设备之一。尤其在航空航天靶场试验、常规武器试验、网络服务器、政府机构设备、通信、交通、电力等领域中都有广泛的应用:", IRIG-B码是标准的每帧一秒的时间码.具有申行格式,携带丰富的编码信息,传输相对比较简单,也适合实际的使用习惯。国际上通用IR1G-B码格式的时间码,作为时间的同步的标准。
IRIG-B格式,简称B码,是将时间同步信号和秒、分、时、天等时间码信息加载到信号载体中。GPS系统接受卫星时间信号,输出IRIG- B时间码序列,变电站智能设备可以挂在统一的对时总线上进行时间同步。
B码信号是每秒一帧的时间串码,一帧串码中包含100个码元,每个码元占用10ms时间,其基本的码元是“0”码元、“1”码元和“P”码元。码元“0”和“1”对应的脉冲宽度为2ms和5ms,“P”码元是位置码元,对应的脉冲宽度为 8 ms,B码信息的基本码元的示意图如图所示。

每秒一帧的 B 码脉冲序列结构示意图见图。连续两个“P”码元表明整秒的开始, 第二个“P”码元的脉冲前沿是“准时”参考点,定义其为“Pr”。每10个码元有一个位置码元, 共有10个,定义其为 P1,P2, …, P9, P0。B码时间格式的时序为秒-分-时-天,所占信息位为秒7位、分7位、时6位、天10位,其位置在P0~P5之间。若从“Pr”开始对码元进行编号,分别定义为第0,1,2,…,99码元,则“秒”信息位于第1,2,3,4,6,7,8码元,“分”信息位于第10,11,12,13,15,16,17码元,“时”信息位于第20,21,22,23,25,26码元,“天” 信息位于第30,31,32,33,35,36,37,38,40,41码元。天、时、分、秒用BCD码表示,低位在前,高位在后,个位在前,十位在后,个位和十位间有一个脉冲宽度为 2 ms的索引标志码元。控制功能码位于P5~P8之间。从 P8 码元开始是SBS时间码,SBS时间码是直接用二进制的秒信号表示一天时间的时间编码方法,共 17位二进制信号,每天重复。

秒个位:0001,低前高后(通常为8421BCD码,此处可理解为1248BCD码),为8;
秒十位:000,为0;
分个位:0001,为8;
分十位:001,为4;
时个位:1000,为1;
时十位:00,为0;
天个位:1000,为1;
天十位:1010,为5;
天百位:01,为2;
年个位(位置在P50-P53):1000,为1;
年十位(位置在P55-P58):0100,为2
则该B码对时为21年第251天01时48分08秒

四、B码解析模块的设计
绘制模块框图及波形图

编写模块代码
module b_code
#(
parameter CNT_MAX_P = 32'd999,
parameter CNT_MAX_0 = 32'd249,
parameter CNT_MAX_1 = 32'd624,
//码元编码
parameter mayuan_p = 2'b10 ,
parameter mayuan_0 = 2'b00 ,
parameter mayuan_1 = 2'b01
)
(
input wire clk ,
input wire rst_n ,
input wire ex_b_code ,
output reg [3:0] miao_gewei ,
output reg [2:0] miao_shiwei ,
output reg [3:0] fen_gewei ,
output reg [2:0] fen_shiwei ,
output reg [3:0] shi_gewei ,
output reg [1:0] shi_shiwei ,
output reg [3:0] day_gewei ,
output reg [3:0] day_shiwei ,
output reg [1:0] day_baiwei ,
output reg [3:0] year_gewei ,
output reg [3:0] year_shiwei
);
reg ex_b_code_r ;
reg flag_fall ;
reg flag_fall_r ;
reg [31:0] cnt_high ;
reg [1:0] now_mayuan ;
reg [1:0] last_mayuan ;
reg two_p_flag ;
reg [7:0] cnt_mayuan ;
// ex_b_code_r:将ex_b_code打一拍
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
ex_b_code_r <= 1'b0;
else
ex_b_code_r <= ex_b_code;
end
// flag_fall:采集ex_b_code_r的下降沿
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
flag_fall <= 1'b0;
else if(ex_b_code_r && ~ex_b_code)
flag_fall <= 1'b1;
else
flag_fall <= 1'b0;
end
//flag_fall_r
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
flag_fall_r <= 1'b0;
else
flag_fall_r <= flag_fall;
end
// cnt_high:用于计数ex_b_code为高电平的时钟个数
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt_high <= 32'd0;
else if(flag_fall)
cnt_high <= 32'd0;
else if(ex_b_code)
cnt_high <= cnt_high + 1'b1;
else
cnt_high <= cnt_high;
end
// now_mayuan:当前的码元
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
now_mayuan <= 2'b11;
else if(flag_fall && (cnt_high <= CNT_MAX_P + 32'd10 && cnt_high >= CNT_MAX_P – 32'd10))
now_mayuan <= mayuan_p;
else if(flag_fall && (cnt_high <= CNT_MAX_0 + 32'd10 && cnt_high >= CNT_MAX_0 – 32'd10))
now_mayuan <= mayuan_0;
else if(flag_fall && (cnt_high <= CNT_MAX_1 + 32'd10 && cnt_high >= CNT_MAX_1 – 32'd10))
now_mayuan <= mayuan_1;
else
now_mayuan <= now_mayuan;
end
// last_mayuan:上一个时刻的码元
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
last_mayuan <= 2'b11;
else
last_mayuan <= now_mayuan;
end
// two_p_flag:双p检测,当检测到双p则拉高;当码元序号到60时拉低
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
two_p_flag <= 1'b0;
else if(last_mayuan == mayuan_p && now_mayuan == mayuan_p
&& flag_fall_r)
two_p_flag <= 1'b1;
else if(cnt_mayuan == 8'd60 && flag_fall)
two_p_flag <= 1'b0;
else
two_p_flag <= two_p_flag;
end
// cnt_mayuan:计数码元序号
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt_mayuan <= 8'd0;
else if(cnt_mayuan == 8'd60 && flag_fall)
cnt_mayuan <= 8'd0;
else if(two_p_flag && flag_fall)
cnt_mayuan <= cnt_mayuan + 1'b1;
else
cnt_mayuan <= cnt_mayuan;
end
// miao_gewei:提取秒的个位(2-5) [3:0]
// miao_shiwei:提取秒的十位(7-9) [2:0]
// fen_gewei:提取分的个位(11-14) [3:0]
// fen_shiwei:提取分的十位(16-18) [2:0]
// shi_gewei:提取时的个位(21-24) [3:0]
// shi_shiwei:提取时的十位(26-27) [1:0]
// day_gewei:提取天的个位(31-34) [3:0]
// day_shiwei:提取天的十位(36-39) [3:0]
// day_baiwei:提取天的百位(41-42) [1:0]
// year_gewei:提取年的个位(51-54) [3:0]
// year_shiwei:提取年的十位(56-59)[3:0]
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
miao_gewei <= 4'd0;
miao_shiwei <= 3'd0;
fen_gewei <= 4'd0;
fen_shiwei <= 3'd0;
shi_gewei <= 4'd0;
shi_shiwei <= 2'd0;
day_gewei <= 4'd0;
day_shiwei <= 4'd0;
day_baiwei <= 2'd0;
year_gewei <= 4'd0;
year_shiwei <= 4'd0;
end
else case(cnt_mayuan)
8'd2 – 1'b1:miao_gewei[0] <= now_mayuan[0];
8'd3 – 1'b1:miao_gewei[1] <= now_mayuan[0];
8'd4 – 1'b1:miao_gewei[2] <= now_mayuan[0];
8'd5 – 1'b1:miao_gewei[3] <= now_mayuan[0];
8'd7 – 1'b1:miao_shiwei[0] <= now_mayuan[0];
8'd8 – 1'b1:miao_shiwei[1] <= now_mayuan[0];
8'd9 – 1'b1:miao_shiwei[2] <= now_mayuan[0];
8'd11 – 1'b1:fen_gewei[0] <= now_mayuan[0];
8'd12 – 1'b1:fen_gewei[1] <= now_mayuan[0];
8'd13 – 1'b1:fen_gewei[2] <= now_mayuan[0];
8'd14 – 1'b1:fen_gewei[3] <= now_mayuan[0];
8'd16 – 1'b1:fen_shiwei[0] <= now_mayuan[0];
8'd17 – 1'b1:fen_shiwei[1] <= now_mayuan[0];
8'd18 – 1'b1:fen_shiwei[2] <= now_mayuan[0];
8'd21 – 1'b1:shi_gewei[0] <= now_mayuan[0];
8'd22 – 1'b1:shi_gewei[1] <= now_mayuan[0];
8'd23 – 1'b1:shi_gewei[2] <= now_mayuan[0];
8'd24 – 1'b1:shi_gewei[3] <= now_mayuan[0];
8'd26 – 1'b1:shi_shiwei[0] <= now_mayuan[0];
8'd27 – 1'b1:shi_shiwei[1] <= now_mayuan[0];
8'd31 – 1'b1:day_gewei[0] <= now_mayuan[0];
8'd32 – 1'b1:day_gewei[1] <= now_mayuan[0];
8'd33 – 1'b1:day_gewei[2] <= now_mayuan[0];
8'd34 – 1'b1:day_gewei[3] <= now_mayuan[0];
8'd36 – 1'b1:day_shiwei[0] <= now_mayuan[0];
8'd37 – 1'b1:day_shiwei[1] <= now_mayuan[0];
8'd38 – 1'b1:day_shiwei[2] <= now_mayuan[0];
8'd39 – 1'b1:day_shiwei[3] <= now_mayuan[0];
8'd41 – 1'b1:day_baiwei[0] <= now_mayuan[0];
8'd42 – 1'b1:day_baiwei[1] <= now_mayuan[0];
8'd51 – 1'b1:year_gewei[0] <= now_mayuan[0];
8'd52 – 1'b1:year_gewei[1] <= now_mayuan[0];
8'd53 – 1'b1:year_gewei[2] <= now_mayuan[0];
8'd54 – 1'b1:year_gewei[3] <= now_mayuan[0];
8'd56 – 1'b1:year_shiwei[0] <= now_mayuan[0];
8'd57 – 1'b1:year_shiwei[1] <= now_mayuan[0];
8'd58 – 1'b1:year_shiwei[2] <= now_mayuan[0];
8'd59 – 1'b1:year_shiwei[3] <= now_mayuan[0];
default:if(!two_p_flag)
begin
miao_gewei <= 4'd0;
miao_shiwei <= 3'd0;
fen_gewei <= 4'd0;
fen_shiwei <= 3'd0;
shi_gewei <= 4'd0;
shi_shiwei <= 2'd0;
day_gewei <= 4'd0;
day_shiwei <= 4'd0;
day_baiwei <= 2'd0;
year_gewei <= 4'd0;
year_shiwei <= 4'd0;
end
else
begin
miao_gewei <= miao_gewei ;
miao_shiwei <= miao_shiwei;
fen_gewei <= fen_gewei ;
fen_shiwei <= fen_shiwei ;
shi_gewei <= shi_gewei ;
shi_shiwei <= shi_shiwei ;
day_gewei <= day_gewei ;
day_shiwei <= day_shiwei ;
day_baiwei <= day_baiwei ;
year_gewei <= year_gewei ;
year_shiwei <= year_shiwei;
end
endcase
end
endmodule
编写仿真代码
`timescale1ns/1ps
module b_code_tb ();
//125Mhz时钟计算时长
parameter time_10ms = 32'd1249 ;//码元长度
parameter time_8ms = 32'd999 ;//P码高电平时间
parameter time_5ms = 32'd624 ;//1码高电平时间
parameter time_2ms = 32'd249 ;//0码高电平时间
reg clk_125mhz ;//125Mhz时钟
reg rst_n ;
reg ex_b_code ;
initial
begin
clk_125mhz=1'b0;
rst_n =1'b0;
ex_b_code =1'b0;
#50
rst_n =1'b1;
end
always #4clk_125mhz = ~clk_125mhz;
//定义100个8bit的wire类型的变量
wire [7:0] mem [0:99] ;
assign mem[0] = 8'h70 ; //p
assign mem[1] = 8'h70 ; //p
assign mem[2] = 8'h30 ; //0
assign mem[3] = 8'h30 ; //0
assign mem[4] = 8'h30 ; //0
assign mem[5] = 8'h31 ; //1
assign mem[6] = 8'h30 ; //0
assign mem[7] = 8'h30 ; //0
assign mem[8] = 8'h30 ; //0
assign mem[9] = 8'h30 ; //0
assign mem[10] = 8'h70 ; //p
assign mem[11] = 8'h30 ; //0
assign mem[12] = 8'h30 ; //0
assign mem[13] = 8'h30 ; //0
assign mem[14] = 8'h31 ; //1
assign mem[15] = 8'h30 ; //0
assign mem[16] = 8'h30 ; //0
assign mem[17] = 8'h30 ; //0
assign mem[18] = 8'h31 ; //1
assign mem[19] = 8'h30 ; //0
assign mem[20] = 8'h70 ; //p
assign mem[21] = 8'h31 ; //1
assign mem[22] = 8'h30 ; //0
assign mem[23] = 8'h30 ; //0
assign mem[24] = 8'h30 ; //0
assign mem[25] = 8'h30 ; //0
assign mem[26] = 8'h30 ; //0
assign mem[27] = 8'h30 ; //0
assign mem[28] = 8'h30 ; //0
assign mem[29] = 8'h30 ; //0
assign mem[30] = 8'h70 ; //p
assign mem[31] = 8'h31 ; //1
assign mem[32] = 8'h30 ; //0
assign mem[33] = 8'h30 ; //0
assign mem[34] = 8'h30 ; //0
assign mem[35] = 8'h30 ; //0
assign mem[36] = 8'h31 ; //1
assign mem[37] = 8'h30 ; //0
assign mem[38] = 8'h31 ; //1
assign mem[39] = 8'h30 ; //0
assign mem[40] = 8'h70 ; //p
assign mem[41] = 8'h30 ; //0
assign mem[42] = 8'h31 ; //1
assign mem[43] = 8'h30 ; //0
assign mem[44] = 8'h30 ; //0
assign mem[45] = 8'h30 ; //0
assign mem[46] = 8'h30 ; //0
assign mem[47] = 8'h30 ; //0
assign mem[48] = 8'h30 ; //0
assign mem[49] = 8'h30 ; //0
assign mem[50] = 8'h70 ; //p
assign mem[51] = 8'h31 ; //1
assign mem[52] = 8'h30 ; //0
assign mem[53] = 8'h30 ; //0
assign mem[54] = 8'h30 ; //0
assign mem[55] = 8'h30 ; //0
assign mem[56] = 8'h30 ; //0
assign mem[57] = 8'h31 ; //1
assign mem[58] = 8'h30 ; //0
assign mem[59] = 8'h30 ; //0
assign mem[60] = 8'h70 ; //p
assign mem[61] = 8'h30 ; //0
assign mem[62] = 8'h30 ; //0
assign mem[63] = 8'h30 ; //0
assign mem[64] = 8'h30 ; //0
assign mem[65] = 8'h30 ; //0
assign mem[66] = 8'h30 ; //0
assign mem[67] = 8'h30 ; //0
assign mem[68] = 8'h30 ; //0
assign mem[69] = 8'h30 ; //0
assign mem[70] = 8'h70 ; //p
assign mem[71] = 8'h30 ; //0
assign mem[72] = 8'h30 ; //0
assign mem[73] = 8'h30 ; //0
assign mem[74] = 8'h30 ; //0
assign mem[75] = 8'h30 ; //0
assign mem[76] = 8'h31 ; //1
assign mem[77] = 8'h30 ; //0
assign mem[78] = 8'h30 ; //0
assign mem[79] = 8'h30 ; //0
assign mem[80] = 8'h70 ; //p
assign mem[81] = 8'h30 ; //0
assign mem[82] = 8'h30 ; //0
assign mem[83] = 8'h30 ; //0
assign mem[84] = 8'h31 ; //1
assign mem[85] = 8'h31 ; //1
assign mem[86] = 8'h30 ; //0
assign mem[87] = 8'h31 ; //1
assign mem[88] = 8'h30 ; //0
assign mem[89] = 8'h31 ; //1
assign mem[90] = 8'h70 ; //p
assign mem[91] = 8'h30 ; //0
assign mem[92] = 8'h30 ; //0
assign mem[93] = 8'h31 ; //1
assign mem[94] = 8'h31 ; //1
assign mem[95] = 8'h30 ; //0
assign mem[96] = 8'h30 ; //0
assign mem[97] = 8'h30 ; //0
assign mem[98] = 8'h30 ; //0
assign mem[99] = 8'h30 ; //0
//状态机参数定义
parameter idel = 4'd0 ; //判断码元类型
parameter s0 = 4'd1 ; //模拟发送0码元
parameter s1 = 4'd2 ; //模拟发送1码元
parameter s2 = 4'd3 ; //模拟发送p码元
parameter s3 = 4'd4 ;//判断一帧是否发送完整
reg [3:0] state ;
reg [31:0] cnt_10ms ;
reg [7:0] num ;
always @(posedge clk_125mhz ,negedge rst_n)
begin
if (~rst_n)
begin
num <= 8'd96 ;//模拟系统启动接收到的B码是第96个码元开始
cnt_10ms <= 32'd0 ;
state <= idel ;
ex_b_code<= 1'b1 ;
end
else
case (state)
idel://判断码元类型,确定要模拟发送的码元
if (mem[num] == 8'h30)
state <= s0 ;
else if (mem[num] == 8'h31)
state <= s1 ;
else if (mem[num] == 8'h70)
state <= s2 ;
else
state <= state ;
s0: //模拟发送0码元
if (cnt_10ms == time_10ms – 2'd2 ) //s3和idle 需要占用两个时钟周期
begin
cnt_10ms <= 32'd0 ;
state <= s3 ;
end
else if (cnt_10ms <= time_2ms )
begin
ex_b_code <= 1'b1 ;
cnt_10ms <= cnt_10ms + 1'b1 ;
end
else
begin
ex_b_code <= 1'b0 ;
cnt_10ms <= cnt_10ms + 1'b1 ;
end
s1://模拟发送1码元
if (cnt_10ms == time_10ms – 2'd2 )
begin
cnt_10ms <= 32'd0 ;
state <= s3 ;
end
else if (cnt_10ms <= time_5ms )
begin
ex_b_code <= 1'b1 ;
cnt_10ms <= cnt_10ms + 1'b1 ;
end
else
begin
ex_b_code <= 1'b0 ;
cnt_10ms <= cnt_10ms + 1'b1 ;
end
s2: //模拟发送P码元
if (cnt_10ms == time_10ms – 2'd2 )
begin
cnt_10ms <= 32'd0 ;
state <= s3 ;
end
else if (cnt_10ms <= time_8ms )
begin
ex_b_code <= 1'b1 ;
cnt_10ms <= cnt_10ms + 1'b1 ;
end
else
begin
ex_b_code <= 1'b0 ;
cnt_10ms <= cnt_10ms + 1'b1 ;
end
s3: //判断一帧数据是否发送完整
if ( num == 8'd99 )
begin
num <= 8'd0 ;
state <= idel ;
end
else
begin
num <= num + 1'b1 ;
state <= idel ;
end
default: state <= idel ;
endcase
end
b_code b_code_inst
(
.clk (clk_125mhz) ,//常用b码时钟125MHz
.rst_n (rst_n ) ,//全局复位信号
.ex_b_code (ex_b_code ) ,//用于解析的b码信号
.miao_gewei (),//解析b码时间(年、日、时、分、秒)
.miao_shiwei (),//例(21年251天01:48:08)
.fen_gewei (),
.fen_shiwei (),
.shi_gewei (),
.shi_shiwei (),
.day_gewei (),
.day_shiwei (),
.day_baiwei (),
.year_gewei (),
.year_shiwei ()
);
endmodule
仿真验证

仿真验证通过,解析时间为21年251天01:48:08.

