【芯片前端】仿真向/基于静态随机函数的单比特跨时钟同步器

前言

因为后面我想做一些其他的实验,需要一个用于仿真的模拟亚稳态的单比特同步模块,需要满足几个需求:

1.在第一拍出发跨异步亚稳态,即发生信号跳变时,同步器第一拍的结果随机为0或者为1;

2.同步器例化多份,每一个inst亚稳态的恢复值随机,横向之间互相没有关系;

3.同一个inst,输入信号跳变,每次亚稳态恢复的值随机,纵向之间相互没有关系;

4.亚稳态恢复结果能够被seed控制,稳定复现;

其实这几个需求,核心还是之前在另外一个博文里探讨过的内容,如何在静态模块中做可控制的随机:

【验证小白】静态模块module/interface中的$urandom可控随机探索

这次实际是一次具体的使用吧。

代码

每次有信号跳变时,需要在RTL中触发一次随机,将同步器的第一拍输出随机为0或者1(实际就是把打三拍之后的亚稳态恢复值,聚在第一拍模拟完成)。

第一步,做用来产生随机数的function,思路就是另一篇博客中说的方式,通过%m来差异化每一个inst随机时的%urandom的种子;

/*for module random ctrl by seed*/
string   path_str;
initial  path_str = $psprintf(path_str, "%m");

function integer urandom_range(); 
    input integer min, max; 
    integer seed, i; 
    begin 
        seed = $urandom(); 
        for(i=path_str.len; i>=0; i=i-1)begin 
            seed = seed ^ path_str.getc(i); 
            seed = $urandom(seed); 
        end 
        urandom_range = min + $abs(seed % (max - min));
    end 
endfunction
/*end*/

第二步,判定输入信号是否跳变,我的做法就是,在i_clk和o_clk分别做一个i_sync_ff(i_sync_ff为实际的跨异步信号)的打拍i_sync_ff1/o_sync_org0,当i_sync_ff与i_sync_ff1保持一致或i_sync_ff与o_sync_org0保持一致时就认为i_sync_ff稳定了足够长的时间,不会触发亚稳态的问题(分别对应快转慢和慢转快);

reg o_sync_org0;
always @(posedge o_clk or negedge o_rst_n) begin
    if(o_rst_n == 1'b0)begin
        o_sync_org0 <= 1'b0;
    end
    else begin
        o_sync_org0 <= i_sync_ff;
    end
end
wire i_sync_hold = (i_sync_ff1 == i_sync_ff0) | (o_sync_org0 == i_sync_ff0);

第三步,在判定信号跳变时,触发亚稳态问题以及随机恢复;

reg o_sync_ff0;
always @(posedge o_clk or negedge o_rst_n) begin
    if(o_rst_n == 1'b0)begin
        o_sync_ff0 <= 1'b0;
    end
    else begin
        if(i_sync_hold)begin
            o_sync_ff0 <= i_sync_ff;
        end
        else begin
            if(urandom_range(1,10) >= 5)begin
                o_sync_ff0 <= ~i_sync_ff;
            end
            else begin
                o_sync_ff0 <= i_sync_ff;
            end
        end
    end
end

第四步,把o_sync_ff0再打两拍,作为同步器的最终输出;

reg o_sync_ff1, o_sync_ff2;
always @(posedge o_clk or negedge o_rst_n) begin
    if(o_rst_n == 1'b0)begin
        o_sync_ff1 <= 1'b0;
        o_sync_ff2 <= 1'b0;
    end
    else begin
        o_sync_ff1 <= o_sync_ff0;
        o_sync_ff2 <= o_sync_ff1;
    end
end

assign o_sync     = o_sync_ff2;

第五步,把o_sync_org0也打两拍输出,作为完全没有亚稳态情况下的参考输出;

reg o_sync_org1, o_sync_org2;
always @(posedge o_clk or negedge o_rst_n) begin
    if(o_rst_n == 1'b0)begin
        o_sync_org1 <= 1'b0;
        o_sync_org2 <= 1'b0;
    end
    else begin
        o_sync_org1 <= o_sync_org0;
        o_sync_org2 <= o_sync_org1;
    end
end
assign o_sync_org = o_sync_org2;

第六步,搭一个简易定向验证环境,测一下各种功能是否能出现,这个就请参考下文吧:

【验证小白】编译、仿真与波形 —— 基于VCS的通用superbench平台搭建

OK,模拟亚稳态的单比特三拍同步器就完成了,仿真一下波形看看各种情况是否有触发;

波形

电平信号跳变为1时,亚稳态恢复为错误值,导致晚一拍采样到 1;

电平信号跳变为0时,亚稳态恢复为错误值,导致晚一拍采样到 0;

 电平信号跳变为0时,亚稳态恢复为正确值;

 电平信号跳变为1时,亚稳态恢复为正确值;

脉冲信号,被完全正确采样;

脉冲信号,跳变为1时亚稳态恢复为错误值0,跳变为0时亚稳态恢复为正确值0,亚稳态导致这个脉冲被吃掉了;

 脉冲输入过窄,导致这个脉冲被吃掉了;

 

上升沿亚稳态恢复正常,下降沿恢复异常; 

上升沿 恢复异常,下降沿恢复异常;

 波形看着好像情况是比较完备的哈,我准备先用着如果后面发现问题再说吧~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尼德兰的喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值