VL60. 使用握手信号实现跨时钟域数据传输
描述
分别编写一个数据发送模块和一个数据接收模块,模块的时钟信号分别为clk_a,clk_b。两个时钟的频率不相同。数据发送模块循环发送0-7,在每个数据传输完成之后,间隔5个时钟,发送下一个数据。请在两个模块之间添加必要的握手信号,保证数据传输不丢失。输入描述
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