列表

详情


VL60. 使用握手信号实现跨时钟域数据传输

描述

分别编写一个数据发送模块和一个数据接收模块,模块的时钟信号分别为clk_a,clk_b。两个时钟的频率不相同。数据发送模块循环发送0-7,在每个数据传输完成之后,间隔5个时钟,发送下一个数据。请在两个模块之间添加必要的握手信号,保证数据传输不丢失。
    模块的接口信号图如下:

data_req和data_ack的作用说明:
data_req表示数据请求接受信号。当data_out发出时,该信号拉高,在确认数据被成功接收之前,保持为高,期间data应该保持不变,等待接收端接收数据。
当数据接收端检测到data_req为高,表示该时刻的信号data有效,保存数据,并拉高data_ack。
当数据发送端检测到data_ack,表示上一个发送的数据已经被接收。撤销data_req,然后可以改变数据data。等到下次发送时,再一次拉高data_req。

输入描述

clk_a:发送端时钟信号

clk_b:接收端时钟信号

rst_n:复位信号,低电平有效

data_ack:数据接收确认信号

输出描述

data:发送的数据

data_req:请求接收数据

原站题解

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-06

`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 [2:0]cnt;
    reg data_ack_reg_1,data_ack_reg_2;
    
    always@(posedge clk_a or negedge rst_n)begin
        if(!rst_n)begin
            data_ack_reg_1<=0;
            data_ack_reg_2<=0;
        end
        else begin
            data_ack_reg_1<=data_ack;
            data_ack_reg_2<=data_ack_reg_1;
        end
    end
            
    always@(posedge clk_a or negedge rst_n)begin
        if(!rst_n)begin
            data<=4'b0;
        end
        else if(data_ack_reg_1 && !data_ack_reg_2)
            data<=data+1;
        else
            data<=data;
    end
    
    always@(posedge clk_a or negedge rst_n)begin
        if(!rst_n)
            cnt<=0;
        else if(data_ack_reg_1 && !data_ack_reg_2)
            cnt<=0;
        else if(data_req)
            cnt<=cnt;
        else
            cnt<=cnt+1;
    end
    
    always@(posedge clk_a or negedge rst_n)begin
        if(!rst_n)
            data_req<=0;
        else if(cnt==3'd4)
            data_req<=1;
        else if(data_ack_reg_1 && !data_ack_reg_2)
            data_req<=0;
        else
            data_req=data_req;
    end
    
endmodule

module data_receiver(
    input clk_b,
	input rst_n,
	input  data_req,
	input  [3:0]data,
    output  reg data_ack
	);
    
    reg [3:0]data_reg;
    reg data_req_reg_1;
    reg data_req_reg_2;
    
    
    always@(posedge clk_b or negedge rst_n)begin
        if(!rst_n)begin
            data_req_reg_1<=0;
            data_req_reg_2<=0;
        end
        else begin
            data_req_reg_1<=data_req;
            data_req_reg_2<=data_req_reg_1;
        end
    end
    
    always@(posedge clk_b or negedge rst_n)begin
        if(!rst_n)
            data_ack<=0;
        else if(data_req_reg_1)
            data_ack<=1;
        else if(data_req_reg_2)
            data_ack<=0;
        else
            data_ack=data_ack;
    end
    
    always@(posedge clk_b or negedge rst_n)begin
        if(!rst_n)
            data_reg<=0;
        else if(data_req_reg_2)
            data_reg<=data;
        else
            data_reg<=data_reg;
    end
    
    
endmodule

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-06

`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 ack_1,ack_2;
    reg [7:0] cnt;
    
    always @(posedge clk_a or negedge rst_n) begin
        if(!rst_n) begin
            ack_1<=0;
            ack_2<=0;
        end
        else begin
            ack_1<=data_ack;
            ack_2<=ack_1;
        end
    end
    
    always @(posedge clk_a or negedge rst_n) begin
        if(!rst_n)
            cnt<=0;
        else if(ack_1&!ack_2)
            cnt<=0;
        else if (data_req)
            cnt<=cnt;
        else
            cnt<=cnt+1;
    end
    
    always @(posedge clk_a or negedge rst_n) begin
        if(!rst_n)
            data<=0;
        else if (ack_1&!ack_2)
            data<=data+1;
        else
            data<=data;
    end
    
    always @(posedge clk_a or negedge rst_n) begin
        if(!rst_n)
            data_req<=0;
        else if(cnt==4)
            data_req<=1;
        else if(ack_1&!ack_2)
            data_req<=0;
        else
            data_req<=data_req;
    end
endmodule

module data_receiver(input clk_b,rst_n,data_req,input [3:0] data,
                     output reg data_ack);
    reg [3:0] data_reg;
    reg req_1,req_2;
    
    always @(posedge clk_b or negedge rst_n) begin
        if(!rst_n) begin
            req_1<=0;
            req_2<=0;
        end
        else begin
            req_1<=data_req;
            req_2<=req_1;
        end
    end
    
    always @(posedge clk_b or negedge rst_n) begin
        if(!rst_n)
            data_ack<=0;
        else if(req_1&~req_2)
            data_ack<=1;
        else
            data_ack<=0;
    end
    
    always @(posedge clk_b or negedge rst_n) begin
        if(!rst_n)
            data_reg<=0;
        else if(req_1&~req_2)
            data_reg<=data;
        else
            data_reg<=data_reg;
    end
endmodule    

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-06

`timescale 1ns/1ns
module data_driver(
	input wire clk_a,
	input wire rst_n,
	input wire data_ack,
	output reg [3:0]data,
	output reg data_req
);
    reg [2:0] cnt;
    reg [1:0] data_ack_reg;
    
    
    
    // data gen
    always @(posedge clk_a or negedge rst_n) begin
        if(!rst_n) begin
            data <= 'd0;
        end
        else if(data_ack_reg[1]) begin
            if(data==4'd7) begin
                data <= 'd0;
            end
            else begin
                data <= data + 1'b1;    
            end
        end
    end
    
    // delay 
    always @(posedge clk_a or negedge rst_n) begin
        if(!rst_n) begin
            cnt <= 'd0;
        end
        else if (data_ack_reg[1]) begin
            cnt <= 'd0;
        end
        else begin
            cnt <= cnt + 1'b1;
        end
    end
        
    // data req
        always @(posedge clk_a or negedge rst_n) begin
        if(!rst_n) begin
            data_req <= 'd0;
        end
            else if(cnt==3'd4)begin
            data_req <= 1'b1;
        end
        else if(data_ack_reg[1])begin
            data_req <= 1'b0;
        end
    end
    
    // data_ack_reg
    always @(posedge clk_a or negedge rst_n) begin
        if(!rst_n) begin
            data_ack_reg <= 2'd0;
        end
        else begin
            data_ack_reg <= {data_ack_reg[0], data_ack};
        end
    end
    
    
endmodule

module data_receiver(
	input wire clk_b,
	input wire rst_n,
	
	input wire [3:0]data,
	input wire data_req,
    output reg data_ack
);
    reg [1:0] data_req_reg;
    reg [3:0] data_reg;
    
    always @(posedge clk_b or negedge rst_n) begin
        if(!rst_n) begin
            data_req_reg <= 'd0;
        end
        else begin
            data_req_reg <= {data_req_reg[0], data_req};
        end
    end
    
    always @(posedge clk_b or negedge rst_n) begin
        if(!rst_n) begin
            data_reg <= 'd0;
        end
        else if(data_cap_en) begin
            data_reg <= data;
        end
    end
    
    always @(posedge clk_b or negedge rst_n) begin
        if(!rst_n) begin
            data_ack <= 'd0;
        end
        else if(data_cap_en) begin
            data_ack <= 1'b1;
        end
        else begin
            data_ack <= 1'b0;
        end
    end
    
    assign data_cap_en = data_req_reg[1];  
    
endmodule

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-06

`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_reg1;
    reg data_ack_reg2;
    reg [2:0]count;
    always@(posedge clk_a or negedge rst_n)begin
        if(!rst_n)begin
            data_ack_reg1 <= 1'b0;
            data_ack_reg2 <= 1'b0;
        end
        else begin
            data_ack_reg1 <= data_ack;
            data_ack_reg2 <= data_ack_reg1; 
        end
    end
    always@(posedge clk_a or negedge rst_n)begin
        if(!rst_n)
            data <= 4'd0;
        else if(~data_ack_reg2 && data_ack_reg1)  // 上升沿
            data <= data + 1'b1;
        else
            data <= data;
    end
    always@(posedge clk_a or negedge rst_n)begin
        if(!rst_n)
            count <= 3'b0;
        else if(~data_ack_reg2 && data_ack_reg1)  // 上升沿
            count <= 3'b0;
        else if(data_req)
            count <= count;
        else
            count <= count + 1'b1;
    end
    always@(posedge clk_a or negedge rst_n)begin
        if(!rst_n)
            data_req <= 1'b0;
        else if(count == 3'd4)
            data_req <= 1'b1;
        else if(~data_ack_reg2 && data_ack_reg1)  // 上升沿
            data_req <= 1'b0;
        else
            data_req <= data_req;
    end
endmodule


module data_receiver(
	input clk_b,
	input rst_n,
	input data_req,
	input [3:0]data,
	output reg data_ack
);
    reg [3:0]data_in_reg;
    reg data_req_reg1;
    reg data_req_reg2;
    always@(posedge clk_b or negedge rst_n)begin
        if(!rst_n)begin
            data_req_reg1 <= 1'b0;
            data_req_reg2 <= 1'b0;
        end
        else begin
            data_req_reg1 <= data_req;
            data_req_reg2 <= data_req_reg1; 
        end
    end
    always@(posedge clk_b or negedge rst_n)begin
        if(!rst_n) 
            data_ack <= 1'b0;
        else if(data_req_reg1)
            data_ack <= 1'b1;
        else
            data_ack <= 1'b0;
    end
    always@(posedge clk_b or negedge rst_n)begin
        if(!rst_n) 
            data_in_reg <= 4'd0;
        else if(~data_req_reg2 && data_req_reg1)  // 上升沿
            data_in_reg <= data;
        else
            data_in_reg <= data_in_reg;
    end
endmodule

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-05

`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[2:0]cnt;
    reg ack1,ack2;
    wire flag1;
    always @(posedge clk_a or negedge rst_n) begin
         if(~rst_n) begin
                ack1<=0;
                ack2<=0;
             end
         else begin
          ack1<=data_ack;
            ack2<=ack1;
         end 
    end 
    assign flag1=(~ack2&&ack1) ;    
    always @(posedge clk_a or negedge rst_n) begin
        if(~rst_n) 
            data_req<=0;
        else if(flag1)
            data_req<=0;
        else if(cnt==3'd4)
            data_req<=1;
        else
            data_req<=data_req;
    end
  
    always @(posedge clk_a or negedge rst_n) begin
        if(~rst_n)
            data<=0;
        else if(flag1)
            data<=data+1;
        else
             data<=data;
    end
    
    always@(posedge clk_a or negedge rst_n) begin
            if(~rst_n)
                cnt<=0;
        else if(~data_req) begin
            if(cnt<3'd4)
                cnt<=cnt+1;
            else
                cnt<=cnt;
        end
        else
            cnt<=0;
    end
endmodule

module data_receiver(
	input clk_b,
	input rst_n,
	output reg data_ack,
	input [3:0]data,
	input data_req
	);
    reg req1,req2;
    reg [3:0]data1;
    wire flag2;
    always @ (posedge clk_b or negedge rst_n) begin
        if(~rst_n) begin
            req1<=0;
            req2<=0;
        end
        else begin
            req1<=data_req;
            req2<=req1;
        end
    end
    assign flag2=(~req2&&req1);
    always@(posedge clk_b or negedge rst_n) begin
        if(~rst_n) 
            data_ack<=0;
        else if(flag2)
            data_ack<=1;
         else 
            data_ack<=0;
    end   
    always @(posedge clk_b or negedge rst_n) begin
            if(~rst_n)
                data1<=0;
        else if(flag2)
            data1<=data;
        else 
            data1<=data1;
    end
     
endmodule

上一题