【verilog】CDC跨时钟域处理–多bit信号传输–握手
说明:进行多bit数据跨时钟域处理的步骤:
①clk_a与clk_b时钟域请求信号req的产生:
-产生clk_a时钟域使能信号的下降沿a_en_neg,并将其寄存作为clk_a信号有效的请求信号a_req。但因为当clk_a的应答信号ack_pos有效时,其请求信号无效,所以在将a_en_neg寄存前需要判断此时应答信号ack_pos是否有效(即给D触发器加CE信号),如果有效,则请求信号a_req为0,如果无效,则a_req即为a_en_neg的值。见下图
②data_a_in数据的传输:
对clk_a的请求信号进行跨时钟域处理(打拍),并检测请求信号的上升沿,如果此时为上升沿,则表示clk_b接收到clk_a的有效请求信号,此时可进行数据的传递。如下图
③应答信号ack的产生:
当clk_b时钟域接收到clk_a的请求信号后,即产生应答信号,并将此应答信号同步至clk_a时钟域,反压clk_a时钟域数据的传输。如下图
整体代码如下:
module woshou(
input clka,
input clkb,
input rst_n,
input a_en,
input [7:0] data_a_in,
output reg [7:0] data_b_out,
output b_en,
output ack_a //应答信号
);
reg a_en_d1,a_en_d2;
wire a_en_neg;
reg a_req;//clk_a时钟域的请求信号
reg req_d1,req_d2;//clk_b时钟域的请求信号,由clk_a时钟域的请求信号打拍产生
reg ack_d1,ack_d2;//将clk_b的req_d2作为clk_b的应答信号并同步到clk_a作为clk_a的应答信号
wire ack_pos;//clk_a的应答信号有效,此时clk_a的请求信号无效
//产生a_en下降沿
always@(posedge clka or negedge rst_n)begin
if(!rst_n)begin
a_en_d1 <= 1'b0;
a_en_d2 <= 1'b0;
end
else begin
a_en_d1 <= a_en;
a_en_d2 <= a_en_d1;
end
end
assign a_en_neg = a_en_d2 && (~a_en_d1);
//产生clk_a的请求信号a_req
always@(posedge clka or negedge rst_n)begin
if(!rst_n)
a_req <= 1'b0;
else if(a_en_neg)
a_req <= 1'b1;
else if(ack_pos)
a_req <= 1'b0;
end
//将clk_a的请求信号同步到clk_b
always@(posedge clkb or negedge rst_n)begin
if(!rst_n)begin
req_d1 <= 1'b0;
req_d2 <= 1'b0;
end
else begin
req_d1 <= a_req;
req_d2 <= req_d1;
end
end
//产生应答信号
always@(posedge clka or negedge rst_n)begin
if(!rst_n)begin
ack_d1 <= 1'b0;
ack_d2 <= 1'b0;
end
else begin
ack_d1 <= req_d2;
ack_d2 <= ack_d1;
end
end
assign b_en = (~req_d2) && (req_d1);
assign ack_pos = (~ack_d2) && ack_d1;
assign ack_a = ack_d2;
//数据传输
always@(posedge clkb or negedge rst_n)begin
if(!rst_n)
data_b_out <= 8'd0;
else if(b_en)
data_b_out <= data_a_in;
end
endmodule
整体电路图
波形