FPGA 实现1553总线接口

FPGA 实现1553总线接口

数字式时分制指令/响应性多路传输数据总线MIL-STD-1553B,总线为半双工传输方式,在总线上传输的数据码应是曼切斯特II型双电平码,逻辑1为双极编码信号1/0,逻辑0为双极编码信号0/1,过零跳变发生在每一位时的中点。

总线传输时钟是1MHZ,传输速率1Mb/s,传输内容分为指令字,数据字,状态字,字长为16位加同步头奇偶校验位总共20位,同步头占3位,有效位占16位,校验位占1位。

1553总线有以下特点:通过同步头可以确定是数据字还是指令字或状态字;如果是指令字或状态字可以有测试手段位(第十位)来确定;数据字在传输数据时最高有效位优先传输;有效位不用位或保留位按逻辑0传输。

1553总线接口程序主要有两个模块组成:1数据接收模块 2数据发送模块

数据接收模块,如图一所示:

图一 

此模块主要是实现1553总线接口部分,把接收到的串行数据转换为并行数据,经过同步头处理,奇数校验处理,输出16位有效数据。

端口说明:

input          dec_clk ;   // 8Mhz decoder clock.

input          rst_n ;     // Asynchronous reset.

input          rx_data ;   // Serial transmit data input.

 

output[0:15]  rx_dword ;  // Output data word receive.

output         rx_dval ;   // Indicates data on "rx_data" isvalid. 数据信息有效

output         rx_csw ;    // "rx_dword" has command orstatus word. 指令字或状态字

output         rx_dw ;     // "rx_dword" has data word.  表示数据字有效

output         rx_perr ;   // Indicates parity error in"rx_dword". 校验错误

如下图二,波形图所示,传输前两个字为状态字和指令字(tx_csw),当tx_dw为1时传输数据字,同步头比tx_csw,tx_dw晚半个T1MHZ。

 

 

数据发送模块,如图二所示:

图二

 

 

 

input          enc_clk ;   // 2Mhz encoder clock.

input          rst_n ;     // Asynchronous reset.yi

input[0:15]   tx_dword ;  // Input data word transmit.

input          tx_csw ;   // "tx_dword" has command or status word.

input          tx_dw ;     // "tx_dword" has data word.

 

output         tx_busy ;   // Encoder is not ready to accept next word.

output         tx_data ;   // Serial transmit data output.

output         tx_dval ;   // Indicates data on "tx_data" isvalid.

 

附件程序:

 

//=============================================================================

 

moduledecoder_1553 (

            // Clock and Reset

            dec_clk ,

            rst_n ,

 

            // Inputs

            rx_data ,

 

            // Outputs

            rx_dword ,

            rx_dval ,

            rx_csw ,

            rx_dw ,

            rx_perr

            ) ;

 

 

input          dec_clk ;   // 8Mhz decoder clock.

input          rst_n ;     // Asynchronous reset.

 

input          rx_data ;   // Serial transmit data input.

 

output[0:15]  rx_dword ;  // Output data word receive.

output         rx_dval ;   // Indicates data on "rx_data" isvalid.

output         rx_csw ;    // "rx_dword" has command orstatus word.

output         rx_dw ;     // "rx_dword" has data word.

output         rx_perr ;   // Indicates parity error in"rx_dword".

 

reg[0:15]     rx_dword ;

reg            rx_dval ;

reg            rx_csw ;

reg            rx_dw ;

reg            rx_perr ;

 

reg[0:23]     sync_sftreg ;

reg[0:4]      data_sftreg ;

reg            cnt_enb ;

reg[7:0]      cnt ;

reg[0:16]     dword_int ;

reg            sync_csw_reg ;

reg            sync_dw_reg ;

 

wire           sync_edge ;

wire           data_edge ;

wire           sync_csw ;

wire           sync_dw ;

wire           data_sample ;

wire           parity ;

 

 

// Shiftin the serial data through shift registrs.

always@(posedge dec_clk or negedge rst_n) begin

   if (!rst_n ) begin  

      data_sftreg <= 5'd0 ;

      sync_sftreg <= 24'd0 ;

   end

   else begin

      data_sftreg <={data_sftreg[1:4],rx_data} ;

      sync_sftreg <={sync_sftreg[1:23],data_sftreg[0]} ;

   end

end

 

 

//Detect transitions.

assigndata_edge =  data_sftreg[3] ^ data_sftreg[4];

 

//Detect sync pattern for command and status word

assignsync_csw = (sync_sftreg == 24'hFFF_000) & data_edge ;

 

//Detect sync pattern for data word

assignsync_dw =  (sync_sftreg == 24'h000_FFF)& data_edge ;

 

// Countnumber of clocks to get complete word after

//detecting the sync pattern

always@(posedge dec_clk or negedge rst_n) begin

   if (!rst_n )   

      cnt_enb <= 1'b0 ;

   else if (sync_csw || sync_dw)

      cnt_enb <= 1'b1 ;

   else if (cnt == 'd131)

      cnt_enb <= 1'b0 ;

   else

      cnt_enb <= cnt_enb ;

end

 

always@(posedge dec_clk or negedge rst_n) begin

   if (!rst_n )   

      cnt <= 8'hFF ;

   else if (cnt_enb)

      cnt <= cnt + 1 ;

   else if (!cnt_enb)

      cnt <= 8'hFF ;

   else

      cnt <= cnt ;

end

 

// Generatedata sample points.

assigndata_sample =  (~cnt[2] & ~cnt[1]& ~cnt[0]) ;

 

//register data at every sample point through shift register.

always@(posedge dec_clk or negedge rst_n) begin

   if (!rst_n )   

      dword_int <= 17'h0000 ;

   else if (data_sample && cnt_enb)

      dword_int <={dword_int[1:16],~data_sftreg[2]} ;

   else if (!cnt_enb)

      dword_int <= 17'h0000 ;

   else

      dword_int <= dword_int ;

end

 

//Register command and status sync patter type till the end

// ofdata word.

always@(posedge dec_clk or negedge rst_n) begin

   if (!rst_n )   

      sync_csw_reg <= 1'b0 ;

   else if (sync_csw)

      sync_csw_reg <= 1'b1 ;

   else if (cnt == 'd132)

      sync_csw_reg <= 1'b0 ;

   else

      sync_csw_reg <= sync_csw_reg ;

end

 

//Register data sync patter type till the end of data word.

always@(posedge dec_clk or negedge rst_n) begin

   if (!rst_n )   

      sync_dw_reg <= 1'b0 ;

   else if (sync_dw)

      sync_dw_reg <= 1'b1 ;

   else if (cnt == 'd132)

      sync_dw_reg <= 1'b0 ;

   else

      sync_dw_reg <= sync_dw_reg ;

end

 

//Register the parallel data word and control outputs.

always@(posedge dec_clk or negedge rst_n) begin

   if (!rst_n ) begin   

      rx_dword <= 16'h0000 ;

      rx_dval <= 1'b0 ;

      rx_perr <= 1'b0 ;

      rx_csw  <= 1'b0 ;

      rx_dw   <= 1'b0 ;

   end

   else if (cnt == 'd131) begin

      rx_dword <= dword_int[0:15] ;

      rx_dval <= 1'b1 ;

      rx_perr <= ((^dword_int[0:15]) != dword_int[16]) ;  //odd

      rx_csw  <= sync_csw_reg ;

      rx_dw   <= sync_dw_reg ;

   end

   else begin

      rx_dword <= 16'h0000 ;

      rx_dval <= 1'b0 ;

      rx_perr <= 1'b0 ;

      rx_csw  <= 1'b0 ;

      rx_dw   <= 1'b0 ;

   end

end

 

endmodule

// =============================================================================

 

 

moduleencoder_1553 (

            // Clock and Reset

            enc_clk ,

            rst_n ,

 

            // Inputs

            tx_dword ,

            tx_csw ,

            tx_dw ,

 

            // Outputs

            tx_busy ,

            tx_data ,

            tx_dval

            ) ;

 

 

input          enc_clk ;   // 2Mhz encoder clock.

input          rst_n ;     // Asynchronous reset.yi

 

input[0:15]   tx_dword ;  // Input data word transmit.

input          tx_csw ;    // "tx_dword" has command orstatus word.

input          tx_dw ;     // "tx_dword" has data word.

 

output         tx_busy ;   // Encoder is not ready to accept next word.

output         tx_data ;   // Serial transmit data output.

output         tx_dval ;   // Indicates data on "tx_data" isvalid.

 

reg            cnt_en ;

reg            cnt_en_reg ;

reg[5:0]      busy_cnt ;

reg[0:16]     data_reg ;

reg  [5:0]    sync_bits ;

reg            tx_data ;

reg            tx_dval ;

 

wire           parity ;

wire[0:40]    enc_data ;

wire           data_out ;

 

// Countnumber of clocks required to encode and serialize

// theinput data.

always@(posedge enc_clk or negedge rst_n) begin

   if (!rst_n) 

      cnt_en <= 1'b0 ;

   else if (tx_csw || tx_dw )

      cnt_en <= 1'b1 ;

   else if (busy_cnt == 'd38)

      cnt_en <= 1'b0 ;

   else

      cnt_en <= cnt_en ;

end

 

always@(posedge enc_clk or negedge rst_n) begin

   if (!rst_n)  

      cnt_en_reg <= 1'b0 ;

   else  

      cnt_en_reg <= cnt_en ;

end

 

always@(posedge enc_clk or negedge rst_n) begin

   if (!rst_n) 

      busy_cnt <= 'd0 ;

   else if (cnt_en)

      busy_cnt <= busy_cnt + 1 ;

   else

      busy_cnt <= 'd0 ;

end

 

//Generate busy signal for the user interface.

assigntx_busy = cnt_en ;

 

//Generate parity for the given 16 bit word data.

assignparity = ^(tx_dword) ;

 

//Register input data word along with generated parity.

always@(posedge enc_clk or negedge rst_n) begin

   if (!rst_n) 

      data_reg <= 17'h0000 ;

   else if ((tx_csw || tx_dw) &&!cnt_en)

      data_reg <= {tx_dword, parity} ;

   else if (!cnt_en )

      data_reg <= 17'h0000 ;

   else 

      data_reg <= data_reg ;

end

 

//Determine the sync pattern based on word type.

always@(posedge enc_clk or negedge rst_n) begin

   if (!rst_n) 

      sync_bits <= 6'b000_000 ;

   else if (tx_csw)

      sync_bits <= 6'b111_000 ;

   else if (tx_dw)

      sync_bits <= 6'b000_111 ;

   else

      sync_bits <= sync_bits ;

end

 

//Generate Manchester encoded data for combined sync pattern,

// dataword and parity.

assignenc_data = { sync_bits,

                    data_reg[0], ~data_reg[0],

                    data_reg[1], ~data_reg[1],

                    data_reg[2], ~data_reg[2],

                    data_reg[3], ~data_reg[3],

                    data_reg[4], ~data_reg[4],

                    data_reg[5], ~data_reg[5],

                    data_reg[6], ~data_reg[6],

                    data_reg[7], ~data_reg[7],

                    data_reg[8], ~data_reg[8],

                    data_reg[9], ~data_reg[9],

                    data_reg[10],~data_reg[10],

                    data_reg[11],~data_reg[11],

                    data_reg[12],~data_reg[12],

                    data_reg[13], ~data_reg[13],

                    data_reg[14],~data_reg[14],

                    data_reg[15],~data_reg[15],

                    data_reg[16],~data_reg[16], 1'b0 } ;

                  

 

//Serialize the encoded data

always@(posedge enc_clk or negedge rst_n) begin

   if (!rst_n) begin  

      tx_dval <= 1'b0 ;

      tx_data <= 1'b0 ;

   end

   else if (cnt_en || cnt_en_reg) begin 

      tx_dval <= 1'b1 ;

      tx_data <= enc_data[busy_cnt] ;

   end

   else begin  

      tx_dval <= 1'b0 ;

      tx_data <= 1'b0 ;

   end

end

 

endmodule

//=============================================================================

 

 

仿真程序:

//=============================================================================

 

moduletest_1553 ();

 

 

reg        enc_clk ;

reg        dec_clk ;

reg        rst_n ;

reg[15:0] tx_dword ;

reg        tx_csw ;

reg        tx_dw ;

 

wire       tx_data ;

wire       tx_dval ;

wire       serial_data ;

 

encoder_1553u1_encoder (

            // Clock and Reset

            .enc_clk    ( enc_clk ),

            .rst_n      ( rst_n ),

 

            // Inputs

            .tx_dword   ( tx_dword ),

            .tx_csw     ( tx_csw ),

            .tx_dw      ( tx_dw ),

 

            // Outputs

            .tx_busy    ( ),

            .tx_data    ( tx_data ),

            .tx_dval    ( tx_dval )

            ) ;

 

assignserial_data = (tx_data & tx_dval) ;

 

decoder_1553u1_decoder (

            // Clock and Reset

            .dec_clk    ( dec_clk ),

            .rst_n     ( rst_n ),

 

            // Inputs

            .rx_data    ( serial_data ),

 

            // Outputs

            .rx_dword   ( ),

            .rx_dval    ( ),

            .rx_csw     ( ),

            .rx_dw      ( ),

            .rx_perr    ( )

            ) ;

 

 

initialbegin

   enc_clk <= 1'b0 ;

   dec_clk <= 1'b0 ;

   rst_n   <= 1'b0 ;

   tx_dword <= 16'd0 ;

   tx_csw  <= 1'b0 ;

   tx_dw   <= 1'b0 ;

end

 

always#500 enc_clk = ~enc_clk ;

always#125 dec_clk = ~dec_clk ;

 

initialbegin

   repeat (10) @(posedge enc_clk) ;

   rst_n  <= 1'b1 ;

 

   repeat (39) @(posedge enc_clk) ;

   tx_dword <= 16'h5555 ;

   tx_csw  <= 1'b1 ;

   tx_dw   <= 1'b0 ;

   repeat (1) @(posedge enc_clk) ;

   tx_dword <= 16'h0000 ;

   tx_csw  <= 1'b0 ;

   tx_dw   <= 1'b0 ;

 

   repeat (39) @(posedge enc_clk) ;

   tx_dword <= 16'hABCD ;

   tx_csw  <= 1'b1 ;

   tx_dw   <= 1'b0 ;

   repeat (1) @(posedge enc_clk) ;

   tx_dword <= 16'h0000 ;

   tx_csw  <= 1'b0 ;

   tx_dw   <= 1'b0 ;

 

   repeat (39) @(posedge enc_clk) ;

   tx_dword <= 16'hFFFF ;

   tx_csw  <= 1'b0 ;

   tx_dw   <= 1'b1 ;

   repeat (1) @(posedge enc_clk) ;

   tx_dword <= 16'h0000 ;

   tx_csw  <= 1'b0 ;

   tx_dw   <= 1'b0 ;

 

   repeat (39) @(posedge enc_clk) ;

   tx_dword <= 16'h1234 ;

   tx_csw  <= 1'b0 ;

   tx_dw   <= 1'b1 ;

   repeat (1) @(posedge enc_clk) ;

   tx_dword <= 16'h0000 ;

   tx_csw  <= 1'b0 ;

   tx_dw   <= 1'b0 ;

 

   repeat (5) @(posedge enc_clk) ;

   repeat (39) @(posedge enc_clk) ;

   tx_dword <= 16'h5678 ;

   tx_csw  <= 1'b1 ;

   tx_dw   <= 1'b0 ;

   repeat (1) @(posedge enc_clk) ;

   tx_dword <= 16'h0000 ;

   tx_csw  <= 1'b0 ;

   tx_dw   <= 1'b0 ;

 

   repeat (5) @(posedge enc_clk) ;

   repeat (39) @(posedge enc_clk) ;

   tx_dword <= 16'hAAAA ;

   tx_csw  <= 1'b0 ;

   tx_dw    <= 1'b1 ;

   repeat (1) @(posedge enc_clk) ;

   tx_dword <= 16'h0000 ;

   tx_csw  <= 1'b0 ;

   tx_dw   <= 1'b0 ;

 

 

   repeat (100) @(posedge enc_clk) ;

   $display("---INFO : Simulation Ended,Check waveform");

   $finish ;

end

 

endmodule

  • 2
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值