429通信 FPGA接口设计
429总线协议标准规定了航空电子设备及有关系统间的数字信息传输要求,ARINC429总线结构简单,性能稳定,抗干扰性强,最大优势在于可靠性高,飞机上的429数据总线,用在系统和设备之间传送上千种不同类型的参数,如航向,真空速,马赫数,高度等。
429总线单向传输,传输速度分高低速,高速模式速率是100Kb/s,低速模式速率应用在12-14.5Kb/s(本次设计低速采用12.5K),速率误差范围在1%之内,高速和低速不能在同一条传输总线上传输,数据字以双极回零脉冲形式发送,HI高电平+10v,中电平0v, 低电平-10v,字与字之间以4位0电平分开,这也作为字同步。
FPGA接口收发数据电平转换为429标准总线电气特性,可以利用光电耦合器HPCL_0631的通断实现电平转换,HPCL_0631兼容LSTTL/TTL电平协议,方便同FPGA的I/O直接交联,为保证光耦正常工作,需串联680欧电阻,硬件电路如下图一。信号转换关系图如图二所示。
图一:
图二:
429通信FPGA接口程序主要分为3部分组成:时钟产生模块,并转串数据发送模块(含奇数校验),传转并数据接收模块(不含奇数校验),各模块分别时序仿真。
1、 时钟产生模块
Clk_in 输入10Mhz时钟
Rst 模块复位信号
Select 时钟模式选择(为1产生100K 时钟输出,为0产生12.5K时钟输出)
Bclk 429时钟信号输出
图三 :时钟模块波形图
2、 并转串数据发送模块(含奇校验)
Data_in(30:0)准备发送的31位有效数据(模块内已添加奇数校验);
Bclk 100K/12.5k 429时钟输入
Clk 模块系统时钟10M
In_en 为高表示有有效数据
Reset 模块复位
Ser_outa 高电平空闲状态,低电平表示429逻辑1
Ser_outb 高电平空闲状态,低电平表示429逻辑0
图四:发送数据模块波形图
3、 串转并数据接收模块
Data_out(30:0)准备发送的32位有效数据(奇校验未做处理,含1位奇校验);
Bclk 100K/12.5k 429时钟输入
Clk 模块系统时钟10M
out_en 为高表示数据输出有效
Reset 模块复位
Ser_in_a 高电平空闲状态,低电平表示429逻辑1
Ser_in_b 高电平空闲状态,低电平表示429逻辑0
图五:接收模块波形图
附件源程序:
///clk_div
module clkdiv(
rst, select, clk_in, bclk
);
input rst;
input select; //=1 100kbps /// =0 12.5kbps
input clk_in; //10Mhz
output bclk;
reg[15:0] cnt1=0;
reg bclk=0;
wire [15:0] bps;
wire [7:0] bps_2;
assign bps=select? 50:400;
assign bps_2=bps/2;
always @(posedge clk_in or posedge rst)
begin
if(rst)
bclk<=1'b0;
else if(cnt1==(bps_2-1))
begin
bclk<=~bclk;
cnt1<=cnt1+1;
end
else if (cnt1<(bps-1))
cnt1<=cnt1+1;
else
cnt1<=0;
end
endmodule
///数据接收模块
module rx_data(
clk,reset,bclk,ser_in_a,ser_in_b,data_out,out_en
);
input clk; //1-10M
input reset;
input bclk; // 100k 12.5k
input ser_in_a;
input ser_in_b;
output reg [31:0]data_out;
output reg out_en;
wire ser_in_null;
wire ser_in_dat;
reg [7:0] bclk_cnt;
reg [35:0]data_buf;
assign ser_in_null=ser_in_a & ser_in_b;
assign ser_in_dat=(~ser_in_a) & ser_in_b;
////count 36
always @ (posedge bclk or posedge reset)
begin
if(reset)
bclk_cnt<=0;
else
begin
bclk_cnt<=bclk_cnt+1;
if(bclk_cnt==35)
begin
bclk_cnt<=0;
out_en<=1;
end
else
out_en<=0;
end
end
// data buffer shift register
always @ (posedge bclk or posedge reset)
begin
if (reset)
data_buf <=36'h0;
else if (~ser_in_null)
data_buf <={ser_in_dat, data_buf[35:1]}; ///YOU YI
end
///data_out
always @ (posedge clk or posedge reset)
begin
if (reset)
data_out <=32'hx;
else if (out_en)//(out_en& (data_buf[35]==~^data_buf[34:4]))
data_out <=data_buf[35:4]; ///YOU XIAO BIT
else
data_out <=32'hxxx;
end
endmodule
///数据发送模块
module tx_data(
clk,reset,bclk,ser_outa,ser_outb,data_in,in_en
);
input clk;
input reset;
input bclk; // 100k 12.5k
output ser_outa;
output ser_outb;
input [30:0]data_in;
input in_en;
reg ser_outa,ser_outb;
wire even_odd;
reg [35:0]data_buff;
wire [35:0]data_buf;
reg [7:0] bit_count=0;
reg tx_busy;
assign data_buf[31]=in_en? ~^data_in:0; //ji odd
assign data_buf[35:32]=0;
assign data_buf[30:0]=in_en ? data_in:0;
// output bit counter
always @ (posedge bclk or posedge reset)
begin
if (reset)
bit_count <=8'h0;
else if (in_en)
begin
bit_count <=bit_count + 8'h1;
tx_busy <= 1'b1;
if (bit_count==35)
begin
bit_count <=8'h0;
tx_busy <= 1'b0;
end
end
end
// data shift register
always @ (posedge bclk or posedge reset)
begin
if (reset)
data_buff <=36'b0;
else if (~tx_busy)
data_buff<=data_buf;
else if (tx_busy)
data_buff <={1'b0, data_buff[35:1]};
end
always @(posedge clk or posedge reset)
begin
if (reset)
begin
ser_outa <= 1'b0;
ser_outb <= 1'b0;
end
else if (in_en)
begin
if(data_buff[0]==1)
begin
ser_outa <= data_buff[0]& (~bclk);
ser_outb <=1;
end
else if (data_buff[0]==0)
begin
ser_outa <= 1;
ser_outb <=(~data_buff[0])& (~bclk);
end
else
begin
ser_outa <= 1;
ser_outb <= 1;
end
end
end
endmodule