Verilog 独立Nexys 4时钟随时间同步

Verilog 独立Nexys 4时钟随时间同步,verilog,hardware,hdl,Verilog,Hardware,Hdl,我们正在开发一个程序,需要在两个设备上同步时钟来测量超声波信号的飞行时间 问题是,当我们合成程序并在两个独立的Nexys4 FPGA上测试时,距离会随着时间的推移而减小(0.13 cm/s)。这个比率是恒定的,并且总是在下降,这使我们认为问题出在代码中 当我们只在一个Nexys 4中合成程序时,不会随着时间的推移而减少 我们有一个模块来监听信号(每个从机3个信号,3个从机),称为dataListener:signal SendCommand是UART模块的控制信号,UART模块向SRF02超声波

我们正在开发一个程序,需要在两个设备上同步时钟来测量超声波信号的飞行时间

问题是,当我们合成程序并在两个独立的Nexys4 FPGA上测试时,距离会随着时间的推移而减小(0.13 cm/s)。这个比率是恒定的,并且总是在下降,这使我们认为问题出在代码中

当我们只在一个Nexys 4中合成程序时,不会随着时间的推移而减少

我们有一个模块来监听信号(每个从机3个信号,3个从机),称为dataListener:signal SendCommand是UART模块的控制信号,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
在从同步模块中,
调用
信号通过电缆从主同步模块发送到从同步模块

`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
`时间刻度为1ns/1ps
模块同步(
输入复位,
输入呼叫,
输出寄存器clkSync,
输出寄存器响应
);
始终@(重置或呼叫)开始
如果(重置)开始

clkSync我还没有完全理解你的代码。但是,问题似乎是,您依赖FPGA板上的外部振荡器。如果使用两块电路板,两个振荡器将不会以完全相同的频率运行。因此,如果在启动后仅补偿一次相移,时钟将在一段时间后失步。这就是为什么它只在一块板上工作

有两种可能的解决方案:

  • 仅使用一个时钟源(振荡器)并将时钟转发到另一块板

  • 定期补偿相移


这两种解决方案都要求两块电路板之间或多或少的稳定连接。

在一块电路板上,当它保持同步时,您是否使用两个独立的晶体振荡器?我怀疑不是,所以你看到振荡器的频率漂移。两个电路板使用相同的振荡器,从一个电路板连接到另一个电路板,或在必要时通过射频链路传输同步信号。
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
`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