Single-bit cross-clock domain design for any clock frequency (Hisilicon Baron)

topic description        

        The two clock domains fly bit data, input A lasts for one cycle, and requires output B for one cycle. The clocking of the two clock domains is arbitrary.

topic analysis

        For the single-bit transmission from the slow clock to the fast clock, we usually use two beats. For the single-bit transmission from the fast clock to the slow clock, we usually use pulse stretching, but usually the purpose of this single-bit transmission is to transmit the edge, such as the single-bit transmission of the rstn signal, which lasts long enough for a low effective time, so we asynchronously release and beat two beats in the destination clock domain to transmit the falling edge.

        But here are the requirements of the topic: first, the frequencies of A and B clocks are unknown, so the design we write must be frequency-independent; second, A outputs a cycle, and B also outputs a cycle. That is to say, the data in the A clock domain is transmitted to the B clock domain, the number of data cannot be changed, and the data cannot be wrong. We can use the multi-bit handshake method across clock domains to do this.

problem solving ideas

        Use the multi-bit handshake method across clock domains to implement data handshaking.

①: When A in the A clock domain is pulled high for 1 cycle, we make A valid and always high (when it is fast to slow, it is used for pulse stretching.)

②: After the A_en signal is beat twice in the B clock domain, the rising edge of A_en_two is detected in the B clock domain . If it is detected, the B output is high for 1 cycle . While satisfying the meaning of the question, it actually means that the B clock domain has seen the signal of the A clock domain .

③: Make two beats of A_en_tre in the A clock domain to get B_en_two. When B_en_two is equal to 1, we can pull the A_en signal low, which means that I have seen in the A clock domain that the B clock domain has accepted my signal.

        When A is the slow clock domain and B is the fast clock domain, it is easy to deduce that the above waveform can also be satisfied.

the code

module one_bit_cdc(
    input   rstn    ,
    input   clk_A   ,
    input   A       ,
    input   clk_B   ,
    output  B   
);
reg A_en,A_en_one,A_en_two,A_en_tre;
reg B_en_one,B_en_two;

always @(posedge clk_A)begin
    if(!rstn)begin
        A_en <= 1'b0;
    end
    else if(A)begin
        A_en <= 1'b1;
    end
    else if(B_en_two)begin
        A_en <= 1'b0;
    end
end

always @(posedge clk_B)begin
    if(!rstn)begin
        A_en_one <= 1'b0;
        A_en_two <= 1'b0;
        A_en_tre <= 1'b0;
    end
    else begin
        A_en_one <= A_en;
        A_en_two <= A_en_one;
        A_en_tre <= A_en_two;
    end
end
assign B = A_en_two && (!A_en_tre);

always @(posedge clk_A)begin
    if(!rstn)begin
        B_en_one <= 1'b0;
        B_en_two <= 1'b0;
    end
    else begin
        B_en_one <= A_en_tre;
        B_en_two <= B_en_one;
    end
end

endmodule

testbench

module tb();

wire B;
reg rstn,clk_A,clk_B,A;
initial begin
    rstn <= 1'b0;
    clk_A <= 1'b0;
    clk_B <= 1'b0;
    A <= 1'b0;
    #20
    rstn <= 1'b1;
    #15
    A <= #1 1'b1;
    #10 
    A <= #1 1'b0;
    #300
    $finish();
end

initial begin
    forever #5 clk_A <= ~clk_A;
end

initial begin
    forever #10 clk_B <= ~clk_B;
end

one_bit_cdc u_one_bit_cdc(
    .rstn   (rstn   ),
    .clk_A  (clk_A  ),
    .A      (A      ),
    .clk_B  (clk_B  ),
    .B      (B      )
);

initial begin
    $fsdbDumpfile("one_bit_cdc.fsdb");
    $fsdbDumpvars(0);
end

endmodule

Waveform

Fast Clock Domain A to Slow Clock Domain B

 Slow Clock Domain A to Fast Clock Domain B

The waveform is consistent with the expected waveform we drew before designing.

Guess you like

Origin blog.csdn.net/qq_57502075/article/details/129848576