verilog设计-cdc:多比特信号跨时钟域(DMUX)-优快云博客
跨时钟域同步2---单bit信号同步实战(快到慢+慢到快) - 知乎 (zhihu.com)
IC学习笔记9——多比特信号的跨时钟域处理方法之“MUX/DMUX同步器”_dmux跨时钟域-优快云博客
原理部分可以参考这些文章。1.快到慢。2.慢到快 3.快到慢的testbench 4. 波形
module mult_bit_fast_to_slow_dmux
#(parameter DATAWIDTH = 8)
(
input rst_n,
input clk_fast,
input [DATAWIDTH-1:0] data_fast,
input data_valid_fast,
input clk_slow,
output reg [DATAWIDTH-1:0] data_slow,
output reg data_valid_slow
);
//signal valid fast to slow cdc
reg data_valid_fast_reg;
wire data_valid_slow_ready;
always@(posedge clk_fast or negedge rst_n)begin
if(!rst_n)
data_valid_fast_reg <= 1'b0;
else if(data_valid_fast == 1'b1)
data_valid_fast_reg <= ~data_valid_fast_reg ;
end
reg data_valid_fast2slow_reg0,data_valid_fast2slow_reg1;
always@(posedge clk_slow or negedge rst_n)begin
if(!rst_n)
begin
data_valid_fast2slow_reg0 <= 1'b0;
data_valid_fast2slow_reg1 <= 1'b0;
end
else
begin
data_valid_fast2slow_reg0<= data_valid_fast_reg ;
data_valid_fast2slow_reg1<= data_valid_fast2slow_reg0;
end
end
reg data_valid_fast2slow_reg2;
always@(posedge clk_slow or negedge rst_n)begin
if(!rst_n)
data_valid_fast2slow_reg2 <= 1'b0;
else
data_valid_fast2slow_reg2 <= data_valid_fast2slow_reg1;
end
assign data_valid_slow_ready = data_valid_fast2slow_reg1 ^ data_valid_fast2slow_reg2 ;
always@(posedge clk_slow or negedge rst_n)begin
if(!rst_n)
data_valid_slow<= 0;
else
data_valid_slow<= data_valid_slow_ready ;
end
//data fast to slow cdc
reg [DATAWIDTH-1:0] data_fast_reg;
always@(posedge clk_fast or negedge rst_n)begin
if(!rst_n)
data_fast_reg<= 0;
else
data_fast_reg<= data_fast;
end
always@(posedge clk_slow or negedge rst_n)begin
if(!rst_n)
data_slow <= 0;
else if(data_valid_slow_ready == 1'b1)
data_slow <= data_fast_reg ;
end
endmodule
`timescale 1ns/1ps
module mult_bit_tb();
reg aclk;
reg arst_n;
reg [7:0] data;
reg data_valid;
wire adata_valid;
wire [7:0] adata;
reg bclk;
always #5 bclk=~bclk;
always #3.365 aclk=~aclk;
initial begin
aclk=1;
bclk=1;
arst_n=0;
data_valid=0;
data=0;
#200;
arst_n=1;
//第一次数据
@(posedge bclk)
data_valid=1;
data=1;
#53.84;
@(posedge bclk)
data_valid=0;
#400;
//第二次数据
@(posedge bclk)
data_valid=1;
data=2;
#53.84;
@(posedge bclk)
data_valid=0;
#53.84;
$finish;
end
mult_bit_fast_to_slow_dmux u1(
.clk_fast(aclk),
.rst_n(arst_n),
.clk_slow(bclk),
.data_fast(data),
.data_valid_fast(data_valid),
.data_slow(adata),
.data_valid_slow(adata_valid)
);
endmodule
module mult_bit_slow_to_fast_dmux
#(parameter DATAWIDTH = 8)
(
input rst_n,
input clk_slow,
input [DATAWIDTH-1:0] data_slow,
input data_valid_slow,
input clk_fast,
output reg [DATAWIDTH-1:0] data_fast,
output reg data_valid_fast
);
//signal valid slow to fast cdc
reg data_valid_slow_reg;
always@(posedge clk_slow or negedge rst_n)begin
if(!rst_n)
data_valid_slow_reg <= 1'b0;
else
data_valid_slow_reg <= data_valid_slow;
end
reg data_valid_slow2fast_reg0,data_valid_slow2fast_reg1;
always@(posedge clk_fast or negedge rst_n)begin
if(!rst_n)
begin
data_valid_slow2fast_reg0 <= 1'b0;
data_valid_slow2fast_reg1 <= 1'b0;
end
else
begin
data_valid_slow2fast_reg0 <= data_valid_slow_reg ;
data_valid_slow2fast_reg1 <= data_valid_slow2fast_reg0 ;
end
end
always@(posedge clk_fast or negedge rst_n)begin
if(!rst_n)
data_valid_fast <= 1'b0;
else
data_valid_fast <= data_valid_slow2fast_reg1 ;
end
//data slow to fast cdc
reg [DATAWIDTH-1:0] data_slow_reg;
always@(posedge clk_slow or negedge rst_n)begin
if(!rst_n)
data_slow_reg <= 0;
else
data_slow_reg <= data_slow ;
end
always@(posedge clk_fast or negedge rst_n)begin
if(!rst_n)
data_fast<= 0;
else if(data_valid_slow2fast_reg1 == 1'b1)
data_fast <= data_slow_reg ;
end
endmodule