如何在system-verilog中对时钟进行相位调整?
How to phase clock in system-verilog?
在 System-verilog 中,可以通过以下代码初始化时钟并使其滴答作响:
bit clk;
initial begin
clk <= 0;
end
always #CLOCK_SEMI_PERIOD begin
clk <= ~clk;
end
但是如果我想让时钟在某个阶段滴答作响怎么办?例如,我们有两个时钟,具有不同的半周期,我希望第一个时钟从零开始滴答作响,而第二个时钟从 $urandom_range(6)
ns 开始滴答作响。
___ ___ ___ ___
clk1 ___| |___| |___| |___| |___
____ ____ ____
clk2 _____| |____| |____| |____
我不能只写这样的东西:
module top(output bit clk1,clk2);
parameter CLOCK1_SEMI_PERIOD = 10;
parameter CLOCK2_SEMI_PERIOD = 13;
int phase;
initial begin
clk1 <= 0;
clk2 <= 0;
phase = $urandom_range(9);
end
always #(CLOCK1_SEMI_PERIOD) begin
clk1 <= ~clk1;
end
always #(CLOCK2_SEMI_PERIOD) begin
#phase;
clk2 <= ~clk2;
end
endmodule
因为它会使第二个时钟周期增加 phase
ns。
那我该如何实现这种滴答呢?
使用initial/forever
循环
initial begin
clk1 <= 0;
clk2 <= 0;
phase = $urandom_range(9);
fork
forever #(CLOCK1_SEMI_PERIOD)
clk1 <= ~clk1;
#phase forever #(CLOCK2_SEMI_PERIOD)
clk2 <= ~clk2;
join
end
分配偏斜概念也可用于引入所需阶段,
module top(output bit clk1,clk2);
parameter CLOCK1_SEMI_PERIOD = 10;
parameter CLOCK2_SEMI_PERIOD = 13;
int phase;
reg temp_1_clk2;//Added
wire temp_2_clk2;//Added
initial begin
clk1 <= 0;
clk2 <= 0;
phase = $urandom_range(9);
temp_1_clk2 = 0;
end
always #(CLOCK1_SEMI_PERIOD) begin
clk1 <= ~clk1;
end
always #(CLOCK2_SEMI_PERIOD) begin
temp_1_clk2 <= ~ temp_1_clk2;
end
assign #(phase) temp_2_clk2 = temp_1_clk2;//Introduces the required phase
always @(temp_2_clk2) begin //Output the clock
clk2 = ~ temp_2_clk2;
end
endmodule
另外让我知道上面的代码是否有任何复杂性或者是否可以进行任何优化
谢谢!
在 System-verilog 中,可以通过以下代码初始化时钟并使其滴答作响:
bit clk;
initial begin
clk <= 0;
end
always #CLOCK_SEMI_PERIOD begin
clk <= ~clk;
end
但是如果我想让时钟在某个阶段滴答作响怎么办?例如,我们有两个时钟,具有不同的半周期,我希望第一个时钟从零开始滴答作响,而第二个时钟从 $urandom_range(6)
ns 开始滴答作响。
___ ___ ___ ___
clk1 ___| |___| |___| |___| |___
____ ____ ____
clk2 _____| |____| |____| |____
我不能只写这样的东西:
module top(output bit clk1,clk2);
parameter CLOCK1_SEMI_PERIOD = 10;
parameter CLOCK2_SEMI_PERIOD = 13;
int phase;
initial begin
clk1 <= 0;
clk2 <= 0;
phase = $urandom_range(9);
end
always #(CLOCK1_SEMI_PERIOD) begin
clk1 <= ~clk1;
end
always #(CLOCK2_SEMI_PERIOD) begin
#phase;
clk2 <= ~clk2;
end
endmodule
因为它会使第二个时钟周期增加 phase
ns。
那我该如何实现这种滴答呢?
使用initial/forever
循环
initial begin
clk1 <= 0;
clk2 <= 0;
phase = $urandom_range(9);
fork
forever #(CLOCK1_SEMI_PERIOD)
clk1 <= ~clk1;
#phase forever #(CLOCK2_SEMI_PERIOD)
clk2 <= ~clk2;
join
end
分配偏斜概念也可用于引入所需阶段,
module top(output bit clk1,clk2);
parameter CLOCK1_SEMI_PERIOD = 10;
parameter CLOCK2_SEMI_PERIOD = 13;
int phase;
reg temp_1_clk2;//Added
wire temp_2_clk2;//Added
initial begin
clk1 <= 0;
clk2 <= 0;
phase = $urandom_range(9);
temp_1_clk2 = 0;
end
always #(CLOCK1_SEMI_PERIOD) begin
clk1 <= ~clk1;
end
always #(CLOCK2_SEMI_PERIOD) begin
temp_1_clk2 <= ~ temp_1_clk2;
end
assign #(phase) temp_2_clk2 = temp_1_clk2;//Introduces the required phase
always @(temp_2_clk2) begin //Output the clock
clk2 = ~ temp_2_clk2;
end
endmodule
另外让我知道上面的代码是否有任何复杂性或者是否可以进行任何优化
谢谢!