【BUG记录】一个FOR语句看出MODELSIM和VIVADO差别

在8通道数据输入场景中,代码使用for循环简化处理,导致在Modelsim仿真正常,但在Vivado上板验证时出现异常。问题源于Vivado综合器对for循环内RST条件下的赋值处理不同,优化了变量r_LAST_LEN_REQ_DFF2,从而影响数据长度计算。解决方法是避免在for循环内对相同变量进行多次赋值,确保代码在不同工具下行为一致。
摘要由CSDN通过智能技术生成

项目场景:

一个8通道数据输入场景,所有代码需要写8遍,为了代码简洁使用了for语句,仿真正确,上板验证功能异常


问题描述

使用modelsim仿真一切正常,vivado编译后上板测试异常。仿真testbench输入两个512bit数据,第二个数伴随EOF表示数据结束,随后将这2个数写入DDR。所以DDR写请求时正确的长度应该是2.这里modelsim仿真确实是2,但上板验证时发现ila抓到的请求长度却是64.

 

 

    always @(posedge DDR_USR_CLK)begin 
        if ( DDR_USR_RST )begin 
            r_CAP_DDR_WR_LEN        <= 13'd0 ;
        end  else if  (s_FSM_WR_REQ) begin 
            if(r_CH_WR_REQ[0]) begin
                r_CAP_DDR_WR_LEN    <= r_LAST_LEN_REQ_DFF2[0] ? {r_CNT0 + 1'b1} : 13'd64 ;  
            end else if(r_CH_WR_REQ[1]) begin 
                r_CAP_DDR_WR_LEN    <= r_LAST_LEN_REQ_DFF2[1] ? {r_CNT1 + 1'b1} : 13'd64 ;  
            end else if(r_CH_WR_REQ[2]) begin 
                r_CAP_DDR_WR_LEN    <= r_LAST_LEN_REQ_DFF2[2] ? {r_CNT2 + 1'b1} : 13'd64 ;  
            end else if(r_CH_WR_REQ[3]) begin 
                r_CAP_DDR_WR_LEN    <= r_LAST_LEN_REQ_DFF2[3] ? {r_CNT3 + 1'b1} : 13'd64 ;  
            end  else if(r_CH_WR_REQ[4]) begin 
                r_CAP_DDR_WR_LEN    <= r_LAST_LEN_REQ_DFF2[4] ? {r_CNT4 + 1'b1} : 13'd64 ;  
            end  else if(r_CH_WR_REQ[5]) begin 
                r_CAP_DDR_WR_LEN    <= r_LAST_LEN_REQ_DFF2[5] ? {r_CNT5 + 1'b1} : 13'd64 ;  
            end  else if(r_CH_WR_REQ[6]) begin 
                r_CAP_DDR_WR_LEN    <= r_LAST_LEN_REQ_DFF2[6] ? {r_CNT6 + 1'b1} : 13'd64 ; 
            end  else if(r_CH_WR_REQ[7]) begin 
                r_CAP_DDR_WR_LEN    <= r_LAST_LEN_REQ_DFF2[7] ? {r_CNT7 + 1'b1} : 13'd64 ;           
            end
        end
    end 

编译太慢,本来想通过ECO直接去修改ila的probe,发现搜索不到r_LAST_LEN_REQ_DFF2这个寄存器,一分析难道是被优化了?如果是那长度就永远是64了。

再看r_LAST_LEN_REQ_DFF2的由来,是为了代码简洁在一个for块里产生的。

    generate
    genvar i;
    for (i=0;i<8;i=i+1)
    begin :u_delay_eof_req
    
        delay_proc 
        #(
        .DWIDTH      (1     )  ,
        .DLEN        (1000  )  
        )u_delay_last_req(
        .w_clk_i   (CLK),
        .reset_i   (RST),
        .d_i       (CH_DATA_VLD_EOF[i]),
        .d_o       (s_CH_DATA_DLY_EOF[i])
        );

        always @ (posedge CLK ) begin
            if (RST) begin
                r_LAST_LEN_REQ                    <= 'b0 ;
            end else if(~r_REG_CAPTURE_EN_D2) begin
                r_LAST_LEN_REQ                    <= 'b0 ;
            end else if( s_CH_DATA_DLY_EOF[i]  )begin
                r_LAST_LEN_REQ[i]                 <= 1'b1 ;
            end
        end
        
        always @ (posedge DDR_USR_CLK ) begin
            r_LAST_LEN_REQ_DFF1[i]                <= r_LAST_LEN_REQ[i] ;
            r_LAST_LEN_REQ_DFF2[i]                <= r_LAST_LEN_REQ_DFF1[i] ;
        end           

    end
    endgenerate

回头一去看vivado的警告发现


[Synth 8-6859] multi-driven net on pin Q with 1st driver pin 'u_delay_eof_req[7].r_LAST_LEN_REQ_reg[6]/Q' ["E:/.../CAP_BUF.v":463]

modelsim vlog编译未给出警告

vlog -work work -L mtiAvm -L mtiRnm -L mtiOvm -L mtiUvm -L mtiUPF -L infact C:/Users/nuchu/Desktop/sim_prj/CAP_BUF.v
# Model Technology ModelSim SE-64 vlog 2020.4 Compiler 2020.10 Oct 13 2020
# Start time: 16:54:24 on Feb 21,2023
# vlog -reportprogress 300 -work work -L mtiAvm -L mtiRnm -L mtiOvm -L mtiUvm -L mtiUPF -L infact C:/Users/.../Desktop/sim_prj/CAP_BUF.v 
# -- Compiling module CAP_BUF

# Top level modules:
#     CAP_BUF
# End time: 16:54:24 on Feb 21,2023, Elapsed time: 0:00:0
 

原因分析:

r_LAST_LEN_REQ在for中RST时被赋值了8次,modelsim综合器和vivado综合器对此处理方式不一样,vivado直接给优化了导致功能异常。

所以给我们的启示,

一、以后modelsim即使仿真pass了,vivado综合后也还是要去关注vivado给出的警告。

二、慎用FOR语句,一定仔细再仔细。


解决方案:

generate
    genvar i;
    for (i=0;i<8;i=i+1)
    begin :u_delay_eof_req
    
        delay_proc 
        #(
        .DWIDTH      (1     )  ,
        .DLEN        (1000  )  
        )u_delay_last_req(
        .w_clk_i   (CLK),
        .reset_i   (RST),
        .d_i       (CH_DATA_VLD_EOF[i]),
        .d_o       (s_CH_DATA_DLY_EOF[i])
        );

        always @ (posedge CLK ) begin
            if (RST) begin
                r_LAST_LEN_REQ[i]                 <= 'b0 ;
            end else if(~r_REG_CAPTURE_EN_D2) begin
                r_LAST_LEN_REQ[i]                 <= 'b0 ;
            end else if( s_CH_DATA_DLY_EOF[i]  )begin
                r_LAST_LEN_REQ[i]                 <= 1'b1 ;
            end
        end
        
        always @ (posedge DDR_USR_CLK ) begin
            r_LAST_LEN_REQ_DFF1[i]                <= r_LAST_LEN_REQ[i] ;
            r_LAST_LEN_REQ_DFF2[i]                <= r_LAST_LEN_REQ_DFF1[i] ;
        end           

    end
    endgenerate

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值