2015-12-06 61 views
2

我們正在開發一個程序,需要兩個設備上的同步時鐘來測量超聲波信號的飛行時間。獨立的Nexys 4時鐘隨時間推移而不同步

的問題是,當我們合成程序並測試它的兩個獨立的FPGA Nexys4的距離趨向於隨時間降低(0.13釐米/秒)。這個比例是不變的,並且一直在下降,這導致我們認爲問題出現在代碼中。

當我們只在一個合成程序Nexys 4,沒有減少被認爲是隨着時間的推移。

我們有一個模塊來監聽信號(每個從站3個從站,3個從站),稱爲dataListener:信號SendCommand是UART模塊的控制信號,該模塊向SRF02超聲發送方向和命令,該模塊爲在兩臺設備上完全相同。

module dataListener(
    input mclk, 
    input clkSync, 
    input reset, 
    input rxDataRdy, 
    output wire[7:0] command, 
    output reg[7:0] direction, 
    output reg read, 
    output reg sendCommand, 
    output reg dataChanged, 
    output reg [1:0] slave, 
    output reg [1:0] sensor 
    ); 

parameter dir0 = 8'd0; 
parameter dir1 = 8'd3; 
parameter dir2 = 8'd6; 

parameter rangingCommand = 8'd87; 
parameter readCommand = 8'd94; 

//parameter clkTime = 0.000000001; // 1ns Simulation // 10ns FPGA 
//parameter windowTime = 0.08; // 80 ms 
//parameter listenTime = 0.07; // 70ms 
parameter windowCyclesDuration = 8000000; 
parameter listenCyclesDuration = 7000000; 

reg [54:0] windowCounter; 
reg emitSent; 
reg readSent; 

reg slave1; 
reg slave2; 
reg slave3; 

assign command = emitSent ? readCommand : rangingCommand; 
/////////////////////////////////////////////////////////////////// 

always @(posedge mclk) begin 

    if(reset)begin 
     sensor <= 2'b0; 
     windowCounter <= 55'b0; 
     emitSent <= 0; 
     readSent <= 0; 
      slave <=0; 
    end else begin 
      if(clkSync) begin 

      if(windowCounter >= windowCyclesDuration)begin //Window ended 
       windowCounter <= 55'b0; //resetCounter 
       emitSent <= 0; 
       readSent <= 0; 
       if(sensor == 2'd2)begin 
         sensor <= 2'b0; 
         if(slave == 2'd2) 
          slave <= 2'b0; 
         else 
          slave <= slave+1'b1; 
       end else begin 
        sensor <= sensor + 1'b1; 
       end  
      end else begin 
       windowCounter <= windowCounter + 1'b1; //Window in process 
       if(!emitSent)begin 
        sendCommand <= 1;   
       end 
       else if((windowCounter >= listenCyclesDuration) && !readSent)begin //listen done, time to send the read command 
        sendCommand <= 1;   
       end   
      end 

      if(sendCommand)begin 
       sendCommand <= 0; //Shut down "sendCommand" signal. 
       if(!emitSent) 
        emitSent <= 1; 
       else 
        readSent <= 1; 
      end 
     end 
     /// Process incoming data 
     if(rxDataRdy)begin 
      read <= 1; 
     end else if(read)begin 
      read <= 0; 

     end 
    end 
end 

////////////////////////////////////////////////////////////////// 
always @(sensor) begin 
    case(sensor) 
     2'd0: begin 
      direction <= dir0; 
     end 
     2'd1: begin 
      direction <= dir1; 
     end 
     2'd2: begin 
      direction <= dir2; 
     end 
     default: begin 
      direction <= dir0; 
     end 
    endcase 
end 

endmodule 

從屬設備上的模塊,其發送所述命令:

module slave(
    input mclk, 
    input clkSync, 
    input reset, 
    output [7:0] command, 
    output [7:0] direction, 
    output reg sendCommand, 
    output inWindow 
    ); 

parameter numSlave = 2'b0;   //Between 0-2 
parameter dir=8'd0;     //Depends on the slaves direction 
parameter comm=8'd92; 

assign command = comm; 
assign direction = dir; 

parameter windowCyclesDuration = 8000000; 

reg [54:0] windowCounter; 
reg [1:0] sensor, slave; 
reg commandSent; 
assign inWindow = (slave == numSlave); 

always @(posedge mclk) begin 

    if(reset)begin 
     windowCounter <= 55'b0; 
      sendCommand <=0; 
      commandSent <= 1; 
      slave <= 2'b0; 
      sensor <= 2'b0; 
    end else begin 
      if(clkSync) begin 
      if(windowCounter >= windowCyclesDuration)begin //Window ended 
       windowCounter <= 55'b0; //resetCounter 
        commandSent <= 0; 
       if(sensor == 2'd2)begin 
         sensor <= 2'b0; 
         if(slave == 2'd2) 
          slave <= 2'b0; 
         else 
          slave <= slave + 1'b1; 
       end else begin 
        sensor <= sensor + 1'b1; 
       end  
      end else begin 
        windowCounter <= windowCounter + 1'b1; //Window in process 
        if(inWindow && !commandSent)begin //im in my window and command not sent yet 
         sendCommand <= 1;//send when a new window is about to begin 
         commandSent <= 1; 
        end 
      end 

       if(sendCommand)begin 
        sendCommand <= 0; //Shut down "sendCommand" signal. 
       end 
      end  
    end 
end 

endmodule 

信號clkSync當兩個設備是「同步」時,纔會激活,只在通過電纜起作用的啓動happend然後移除以允許移動。

這裏是主站的同步模塊:

module SyncM(
    input mclk, 
    input reset, 
    input response1, 
    input response2, 
    input response3, 
    output reg call1, 
    output reg call2, 
    output reg call3, 
    output reg clkSync, 
    output reg slave1, 
    output reg slave2, 
    output reg slave3 
    ); 



always @ (posedge mclk) begin 

    if(reset)begin 
     clkSync <= 0; 
     slave1 <= 0; 
     slave2 <= 0; 
     slave3 <= 0; 
     call1 <= 0; 
     call2 <= 0; 
     call3 <= 0; 
    end else begin 

     if(btn && !call1)begin  
      call1 <= 1; 
      call2 <= 1; 
      call3 <= 1; 
      clkSync <= 1; 
     end 

     if(response1) 
       slave1 <= 1; 

     if(response2) 
       slave2 <= 1; 

     if(response3) 
       slave3 <= 1; 
    end 
end 
endmodule 

和從同步模塊,所述call信號是從主發送通過電纜向從屬。

`timescale 1ns/1ps 

module SyncS(
    input reset, 
    input call, 
    output reg clkSync, 
    output reg response 
    ); 


always @ (reset or call) begin 

    if(reset) begin 
     clkSync <= 0; 
     response <= 0;   
    end else begin 
     if (call) begin 
      response <= 1; 
      clkSync <= 1; 
     end 
    end 
end 
endmodule 
+0

在一塊電路板上,當它保持同步時,是否使用了2個獨立的晶體振盪器?我懷疑沒有,所以你看到振盪器漂移的頻率。如果需要,可以使用相同的振盪器,從一個板連接到另一個板,或通過RF鏈路傳送同步信號。 –

回答

4

我還沒有理解你的所有代碼。但是,問題似乎是,您依賴FPGA板上的外部振盪器。如果你使用兩塊電路板,兩個振盪器將不會以完全相同的頻率運行。因此,如果您在啓動後僅對相移進行一次補償,時鐘會在一段時間後失步。這就是爲什麼它只與一個董事會合作。

有兩種可能的解決方案:

  • 只使用一個時鐘源(振盪器)和轉發時鐘到其他電路板。

  • 定期補償相移。

兩種解決方案都需要兩塊板之間或多或少穩定的連接。