解题思路

发送方

①处理收到的响应信号data_ack,进行打2拍处理;

②所发送数据data在收到响应后重新生成,即+1;

③发送请求信号data_req,会用到计数器来记时data_req的时间间隔。

接收方

①处理收到的请求信号data_req,进行打2拍处理;

②收到了请求后,两件事同时进行:a.发送响应, b.数据接收。

代码实现

`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;
    reg [2:0] cnt;
    
    always @ (posedge clk_a or negedge rst_n)
        if (!rst_n) 
        begin
            data_ack_r1 <= 1'b0;
            data_ack_r2 <= 1'b0;
        end
        else
        begin
            data_ack_r1 <= data_ack;
            data_ack_r2 <= data_ack_r1;
        end
    
    always @ (posedge clk_a or negedge rst_n)
        if (!rst_n) 
            data <= 4'b0;
        else if(data_ack_r1 && !data_ack_r2)
            data <= data + 1'b1;
        else
            data <= data;
    
    always @ (posedge clk_a or negedge rst_n)
        if (!rst_n) 
            cnt <= 1'b0;
        else if (data_ack_r1 && !data_ack_r2)
            cnt <= 1'b0;
        else if (data_req)  //正在请求时不计数
            cnt <= cnt;
        else 
            cnt <= cnt + 1'b1;
             
    always @ (posedge clk_a or negedge rst_n)
        if (!rst_n) 
            data_req <= 1'b0;
        else if (cnt == 3'd4)  
            data_req <= 1'b1;
        else if (data_ack_r1 && !data_ack_r2)
            data_req <= 1'b0;
        else 
            data_req <= data_req;
    
endmodule



module data_receiver(
    input clk_b,
    input rst_n,
    output reg data_ack,
    input [3:0]data,
    input data_req
    );
    reg [3:0]data_in_reg;
    reg data_req_1, data_req_2;
    
    always @ (posedge clk_b or negedge rst_n)
        if (!rst_n) begin
            data_req_1 <= 1'b0;
            data_req_2 <= 1'b0;
        end
        else begin
            data_req_1 <= data_req;
            data_req_2 <= data_req_1;
        end
 
    always @ (posedge clk_b or negedge rst_n)
        if (!rst_n) begin
            data_ack <= 1'b0;
            data_in_reg <= 4'b0;
        end
        else if (data_req_1 && !data_req_2) begin
            data_ack <= 1'b1;
            data_in_reg <= data;
        end
        else begin 
            data_ack <= 1'b0;
            data_in_reg <= data_in_reg; 
        end
    
endmodule