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.