0

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

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

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

  1. 我的策略——使用逆变器链来延迟ice40 内部时钟——是一个好策略吗?

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

在此处输入图像描述

请注意,asic_dataX延迟比clk_out延迟短,表明存在问题。

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

感谢您的任何见解!

4

1 回答 1

1

我建议使用已建立的技术,而不是修补延迟。例如,SPI 简单地在一个边沿对数据进行计时,并在另一边改变它们:来源 https://www.ti.com/lit/an/slaa734a/slaa734a.pdf.

实现它的逻辑相当简单。这里是一个 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

正如我们所看到的,数据在上升沿捕获并在下降沿发生变化。如果想避免边缘敏感度的混合,可以使用双倍时钟。

于 2020-07-18T08:36:49.883 回答