`timescale 1ns/1ns
module data_driver(
	input clk_a,
	input rst_n,
	input data_ack,
	output reg [3:0]data,
	output reg data_req
	);
reg data_ack_r1,data_ack_r2;
always @(posedge clk_a or negedge rst_n) begin
	if (!rst_n) begin
		data_ack_r1 <= 'b0;
		data_ack_r2 <= 'b0;
	end
	else begin
		data_ack_r1 <= data_ack;
		data_ack_r2 <= data_ack_r1;
	end
end
always @(posedge clk_a or negedge rst_n) begin
	if (!rst_n) begin
		data <= 'b0;
	end
	else if (data_ack_r1 && !data_ack_r2)begin
		data <= data + 'd1;
	end
end

//同时在data_ack有效之后,开始计数五个时钟,之后发送新的数据,也就是再一次拉高data_req.
reg [2:0] cnt;
always @(posedge clk_a or negedge rst_n) begin
	if (!rst_n) begin
		cnt <= 'd0;
	end
	else if (data_ack_r1 && !data_ack_r2) begin
		cnt <= 'd0;
	end
	else if (data_req)begin
		cnt <= cnt;
	end
	else begin
		cnt <= cnt +'d1;
	end
end

always @(posedge clk_a or negedge rst_n) begin
	if (!rst_n) begin
		data_req <= 'b0;
	end
	else if (cnt == 'd4) begin
		data_req <= 'b1;
	end
	else if (data_ack_r1 && !data_ack_r2)begin
		data_req <= 'b0;
	end
end
endmodule

module data_receiver(
	input clk_b,
	input rst_n,
	input data_req,
	input [3:0] data,
	output reg data_ack
);

reg data_req_r1,data_req_r2;
always @(posedge clk_b or negedge rst_n) begin
	if (!rst_n) begin
		data_req_r1 <= 'b0;
		data_req_r2 <= 'b0;
	end
	else begin
		data_req_r1 <= data_req;
		data_req_r2 <= data_req_r1;
	end
end
reg [2:0] data_o;
always @(posedge clk_b or negedge rst_n) begin
	if (!rst_n) begin
		data_o <= 'b0;
		data_ack <= 'b0;
	end
	else if (data_req_r1 && !data_req_r2 )begin
		data_o <= data;
		data_ack <= 'b1;
	end
	else begin
		data_ack <= 'd0;
		data_o <= data_o;
	end
end

endmodule

关键点在于data信号和控制信号是分开变化考虑的,而不是同时变化。

可以这样想,如果控制信号和data信号的变化趋势相同,那么就不需要使用控制信号来指示了。