Verilog ice40时钟延迟,输出时序分析

Verilog ice40时钟延迟,输出时序分析,verilog,fpga,yosys,ice40,Verilog,Fpga,Yosys,Ice40,我有一个ice40,它驱动ASIC的时钟和数据输入 ice40驱动ASIC时钟的时钟与驱动ice40内部逻辑的时钟相同。问题在于上升时钟触发ice40的内部逻辑,并在上升时钟到达ASIC之前几纳秒改变ice40的数据输出,因此ASIC在上升时钟处观察到错误的数据 我通过使用逆变链延迟ice40的内部时钟而不延迟驱动ASIC的时钟,解决了这个问题。这样,上升时钟在ice40的数据输出改变之前到达ASIC。但这引发了几个问题: 我的策略——使用逆变链延迟ice40内部时钟——是一个好策略吗 为了诊

我有一个ice40,它驱动ASIC的时钟和数据输入

ice40驱动ASIC时钟的时钟与驱动ice40内部逻辑的时钟相同。问题在于上升时钟触发ice40的内部逻辑,并在上升时钟到达ASIC之前几纳秒改变ice40的数据输出,因此ASIC在上升时钟处观察到错误的数据

我通过使用逆变链延迟ice40的内部时钟而不延迟驱动ASIC的时钟,解决了这个问题。这样,上升时钟在ice40的数据输出改变之前到达ASIC。但这引发了几个问题:

  • 我的策略——使用逆变链延迟ice40内部时钟——是一个好策略吗

  • 为了诊断问题,我使用Lattice的iCEcube2分析了内部时钟和输出引脚之间的最小/最大延迟:

  • 请注意,
    asic\u dataX
    延迟比
    clk\u out
    延迟短,表明存在问题

    有没有办法从yosys/nextpnr获得这些信息


    感谢您的任何见解

    我建议使用已有的技术,而不是修补延迟。例如,SPI simple在一边对数据进行时钟设置,并在另一边对其进行更改:

    实现这一点的逻辑相当简单。这里是SPI从机的示例实现:

    module SPI_slave #(parameter WIDTH = 6'd16, parameter phase = 1'b0,
                       parameter polarity = 1'b0, parameter bits = 5) (
        input wire rst,
        input wire CS,
        input wire SCLK,
        input wire MOSI,
        output reg MISO,  
        output wire data_avbl,
        input wire [WIDTH-1:0] data_tx,
        output reg [WIDTH-1:0] data_rx
        );
    
    reg [bits:0]    bitcount;
    reg [WIDTH-1:0] buf_send;            
    
    assign clk          = phase ^ polarity ^ SCLK;
    assign int_rst      = rst | CS;
    assign tx_clk       = clk | CS;
    assign data_avbl    = bitcount == 0;            
                                   
    always @(negedge tx_clk or posedge rst) begin
        MISO <= rst ? 1'b0 : buf_send[WIDTH-1];
    end
    
    always @(posedge clk or posedge int_rst) begin  
        if (int_rst) begin
            bitcount    <= WIDTH;
            data_rx     <= 0;
            buf_send    <= 0;
        end else begin    
            bitcount    <= (data_avbl ? WIDTH : bitcount) - 1'b1;                
            data_rx     <= { data_rx[WIDTH-2:0], MOSI };
            buf_send    <= bitcount == 1 ? data_tx[WIDTH-1:0] : { buf_send[WIDTH-2:0], 1'b0};
        end   
    end
    
    endmodule
    
    模块SPI_从站#(参数宽度=6'd16,参数相位=1'b0,
    参数极性=1'b0,参数位=5)(
    输入线rst,
    输入线CS,
    输入线SCLK,
    输入线MOSI,
    输出寄存器味噌,
    输出线数据_avbl,
    输入线[WIDTH-1:0]数据_tx,
    输出寄存器[WIDTH-1:0]数据\u rx
    );
    reg[位:0]位计数;
    reg[WIDTH-1:0]buf_发送;
    分配clk=相位^极性^ SCLK;
    分配int_rst=rst | CS;
    分配tx_clk=clk | CS;
    分配数据\u avbl=位计数==0;
    始终@(negedge发送时钟或posedge rst)开始
    
    如果clk对上升沿敏感,那么反对改变下降沿数据的理由是什么?例如,SPI就是这样做的。您可以搜索spi verilog模块以查找一些示例。感谢Christian的建议,这可能会奏效。最初我忽略了涉及反转时钟的解决方案(因为ASIC的输出保持时间太短,不允许在负边缘读取数据)。但也许我可以保持所有的边缘敏感,除了ice40的输出触发器是负边缘敏感。我仍然需要弄清楚驱动负边缘触发器的逻辑的时序含义:要么逻辑需要足够快,以击败负边缘(+t_设置),要么足够慢,以使负边缘触发器的输入在负边缘(+t_保持)不受干扰。