时钟域就是时钟信号的“势力范围”。一个时钟域只能存在一个时钟信号,但是一个时钟信号最多可以对应两个时钟域,当其上升沿和下降沿分别都被一部分资源敏感的时候。
在时序逻辑中,正是时钟信号将各个存储单元中的数据一级、一级的推动下去,如果时钟信号突然停止,那么整个时序逻辑也将陷入瘫痪
慢到快的DUT
module slow2quick (
// input
input rst_n , // system reset
input clka , // clockA
input clkb , // clockB
input level_a_in , // pulsee input from clka
// output
output pulse_b_neg , // pulsee output in clkb
output pulse_b_pos , // pulsee output in clkb
output level_b_out // level output in clkb
);
parameter DLY = 1 ; //
reg level_b_d1, level_b_d2, level_b_d3;
always @ (posedge clka or negedge rst_n)
begin
if (!rst_n) begin
level_b_d1 <= #DLY 1'b0;
level_b_d2 <= #DLY 1'b0;
level_b_d3 <= #DLY 1'b0;
end
else begin
level_b_d1 <= #DLY level_a_in;
level_b_d2 <= #DLY level_b_d1;
level_b_d3 <= #DLY level_b_d2;
end
end
assign pulse_b_pos = level_b_d2 & (~level_b_d3);
assign pulse_b_neg = level_b_d3 & (~level_b_d2);
assign level_b_out = level_b_d2;
endmodule
快到慢的DUT
module quick2slow (
// input
input rst_n , // system reset
input clka , // clockA
input clkb , // clockB
input pulse_a_in , // pulsee input from clka
// output
output pulse_b_out , // pulsee output in clkb
output level_b_out // level output in clkb
);
parameter DLY = 1 ; //
reg signal_a;
reg signal_b;
reg signal_b_b1;
reg signal_b_b2;
reg signal_b1_a1;
reg signal_b1_a2;
always @ (posedge clka or negedge rst_n)
begin
if (rst_n == 1'b0)
signal_a <= # DLY 1'b0 ;
else if (pulse_a_in)
signal_a <= # DLY 1'b1 ;
else if (signal_b1_a2)
signal_a <= # DLY 1'b0 ;
else ;
end
always @ (posedge clkb or negedge rst_n)
begin
if (rst_n == 1'b0)
signal_b <= # DLY 1'b0 ;
else
signal_b <= # DLY signal_a ;
end
always @ (posedge clkb or negedge rst_n)
begin
if (rst_n == 1'b0) begin
signal_b_b1 <= # DLY 1'b0 ;
signal_b_b2 <= # DLY 1'b0 ;
end
else begin
signal_b_b1 <= # DLY signal_b ;
signal_b_b2 <= # DLY signal_b_b1 ;
end
end
always @ (posedge clka or negedge rst_n)
begin
if (rst_n == 1'b0) begin
signal_b1_a1 <= # DLY 1'b0 ;
signal_b1_a2 <= # DLY 1'b0 ;
end
else begin
signal_b1_a1 <= # DLY signal_b_b1 ;
signal_b1_a2 <= # DLY signal_b1_a1 ;
end
end
assign pulse_b_out = signal_b_b1 & (~signal_b_b2) ;
assign level_b_out = signal_b_b1 ;
endmodule
TB
`timescale 1ns/1ns
module mul_clk_tb;
reg clka;
reg clkb;
reg rst_n;
reg level_a_in;
wire pulse_b_neg;
wire pulse_b_pos;
wire level_b_out;
reg pulse_a_in;
wire pulse_b_out_l;
wire pulse_b_out_q;
wire pulse_b_out;
slow2quick slow2quick_inst(
.rst_n (rst_n ),
.clka (clka ),
.clkb (clkb ),
.level_a_in (level_a_in ),
.pulse_b_neg (pulse_b_neg ),
.pulse_b_pos (pulse_b_pos ),
.level_b_out (level_b_out_l )
);
quick2slow quick2slow_inst(
.rst_n (rst_n ),
.clka (clka ),
.clkb (clkb ),
.pulse_a_in (pulse_a_in ),
.pulse_b_out (pulse_b_out ),
.level_b_out (level_b_out_q)
);
initial clka = 0;
always#10 clka = ~clka;
initial clkb = 0;
always#100 clkb = ~clkb;
initial begin
rst_n = 1;
#100;
rst_n = 0;
#100;
rst_n = 1;
#10000;
$finish();
end
//generate level_a_in
always @ (posedge clkb or negedge rst_n)
begin
if (!rst_n)
level_a_in <= 0;
else
repeat (100) begin
level_a_in = {$random}%2;
end
end
//generate pulse_a_in
always @ (posedge clkb or negedge rst_n)
begin
if (!rst_n)
pulse_a_in <= 0;
else
repeat (10) begin
pulse_a_in = {$random}%2;
#20;
pulse_a_in = 0;
#200;
end
end
initial begin
$fsdbDumpfile("jacky");
$fsdbDumpvars;
$vcdpluson;
end
endmodule