我正在将 System Verilog 模型移植到 SystemC,但我不确定对这种锁相环时钟驱动方案进行建模的最佳方法。在我看来,在 SV 中驱动时钟是一个手动过程,其中 SystemC 为内核提供了一种方法来为你做这件事。但我不知道 SystemC 如何支持在我正在查看的 SV 模型中手动完成的那种时钟划分。
考虑这个简化的 System Verilog 模型。
module device(
input REFCLKP, // Reference clock, Positive.
input REFCLKN, // Reference Clock, Negative.
...
);
...
reg ck;
reg ck_x2;
reg ck_x3;
wire refclk = REFCLKP & ~REFCLKN;
int unsigned ck_ratio = 10; // divide the reference clock by 10
...
always @(posedge refclk) begin
tm_refclk_period = $time - tm_refclk;
tm_refclk <= $time;
if (tm_refclk_period) begin
for (int i=0; i<ck_ratio; i++) begin
ck <= #(i*tm_refclk_period/ck_ratio) refclk;
ck <= #((i+0.5)*tm_refclk_period/ck_ratio) !refclk;
end
for (int i=0; i<ck_ratio/2; i++) begin
ck_x2 <= #(i*tm_refclk_period/(ck_ratio/2)) refclk;
ck_x2 <= #((i+0.5)*tm_refclk_period/(ck_ratio/2)) !refclk;
end
for (int i=0; i<ck_ratio/3; i++) begin
ck_x3 <= #(i*tm_refclk_period/(ck_ratio/3)) refclk;
ck_x3 <= #((i+0.5)*tm_refclk_period/(ck_ratio/3)) !refclk;
end
end
end
...
endmodule
然后,在测试台中:
initial begin
...
// start the clock
refclk <= #(1e6/rl_ck_mhz) 1'b1;
forever begin
@(posedge refclk) begin
refclk <= #(0.5e6/rl_ck_mhz) 1'b0;
refclk <= #(1e6/rl_ck_mhz) 1'b1;
end
end
end
device dut(
.REFCLKP(refclk),
.REFCLKN(!refclk),
...);
所以我的 SystemC 相当于测试台基本上看起来像
int sc_main(int argc, char* argv[])
{
sc_clock refclk;
...
device dut;
dut.refclk(refclk);
...
}
但是现在我有点坚持如何正确地模拟从参考时钟驱动的内部时钟。我想我可以尝试像 SV 代码这样的手动方法,但这似乎不像 SystemC 方式。我的另一个想法是尝试直接从 驱动所有时钟sc_main
,而不是示例中的 PLL 样式,但我没有经验可以确定它是否会工作。在 SystemC 中做这样的事情有什么约定吗?