简体   繁体   English

跨时钟域,用于罕见地更改数据

[英]Crossing clock domain for rarly changing data

I need to connect a configuration module (running at slower clock) to a worker which runs at higher speed. 我需要将配置模块(以较低的时钟频率运行)连接到以较高速度运行的工作线程。 Standard answer seems to be a FIFO but I thought I come up with a simpler solution which consumes less resources - with drawback of having much higher latency. 标准答案似乎是一个FIFO,但我认为我想出了一个更简单的解决方案,该方案消耗更少的资源-缺点是延迟时间长得多。 Benefit for me is that I don't need to regenerate FIFO IP for each possible size of data. 对我来说,好处是我不需要为每种可能的数据大小重新生成FIFO IP。 In RTL simulation it seems to work (I run into troubles using post-synthesis one unrelated to question). 在RTL模拟中,它似乎起作用(我使用与问题无关的后合成方法遇到麻烦)。

Am I missing something or is the following code correct: 我是否缺少某些内容或以下代码是否正确:

module fifo_int#( // This is bad name. I haven't come up with better yet
    parameter type DATA = logic [31:0]
    )(
    input  logic rst,
    input  logic clk_in,
    input  DATA  din,
    input  logic clk_out,
    output DATA  dout
    );
    DATA dreg;

    enum logic [1:0] {
        IN,
        STABLE,
        WAIT_OUT
    } in_state;
    enum logic [1:0] {
        WAIT_IN,
        WRITE,
        INV
    } out_state;
    logic in_output[3], out_output[3];
    initial begin
        in_state <= IN;
        out_state <= WAIT_IN;
        for (int i = 0; i < 3; i++) begin
            in_output[i] <= 0;
            out_output[i] <= 0;
        end
    end
    always @(posedge clk_in)
    begin
        case (in_state)
        IN: begin
            dreg <= din;
            in_state <= STABLE;
        end
        STABLE: begin
            in_state <= WAIT_OUT;
            in_output[0] <= ~in_output[0];
        end
        WAIT_OUT: begin
            in_state <= (in_output[0] == out_output[2]) ? IN : WAIT_OUT;
        end
        endcase
        out_output[1] <= out_output[0];
        out_output[2] <= out_output[1];
    end
    always @(posedge clk_out)
    begin
        case (out_state)
        WAIT_IN: begin
            out_state <= (in_output[2] == out_output[0]) ? WAIT_IN : WRITE;
        end
        WRITE: begin
            dout <= dreg;
            out_state <= INV;
        end
        INV: begin
            out_output[0] <= ~out_output[0];
            out_state <= WAIT_IN;
        end
        endcase
        in_output[1] <= in_output[0];
        in_output[2] <= in_output[1];
    end
endmodule

If your clocks are asynchronous, you're going to need synchronization. 如果您的时钟是异步的,则将需要同步。

For synchronous clocks, since your slow side is the one producing the data, you don't need any buffering. 对于同步时钟,由于速度较慢的一方是产生数据的一方,因此不需要任何缓冲。 Data is anyway held stable for multiple (fast) clock cycles, so you don't really need any logic between the domains. 无论如何,数据在多个(快速)时钟周期内保持稳定,因此您在域之间实际上并不需要任何逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM