首页 文章

VHDL - 用变量计时一个触发器?

提问于
浏览
1

我在工作中继承了一些传统的VHDL,并一直在试图弄清楚问题 . 首先让我说我对Verilog更有经验但是已经花了一段时间用VHDL来解决这个问题 .

因此,我们的产品自2011年以来一直运行良好 . 但是,我们需要更改FPGA,因此我们正在移植代码 . 该代码的高级视图是FPGA在板载闪存中存储CPU的引导加载程序 . 上电时,CPU读取FPGA以提取引导加载程序 . 在我们的旧设计上它运作良好 . 在新设计中,它在寒冷时不起作用,在温暖的温度下也不是100%可靠 .

我注意到很多代码都完成了我认为奇怪的事情,其中触发器用信号而不是时钟来计时 . 一个例子:

process( N_RESET, DATA_READ, START_ADDRESS, END_ADDRESS )
begin
    if( N_RESET = '0' ) then
        ADDR_TMP    <= START_ADDRESS;

    elsif( DATA_READ'event and (DATA_READ='0') ) then
        if( ADDR_TMP <= END_ADDRESS ) then
            ADDR_TMP <= ADDR_TMP + "10";
            incremented_tmp <= incremented_tmp xor '1';

        end if;
    end if;
end process;

因此,生成的RTL最终成为由DATA_READ计时的触发器 . 数据读取是来自CPU的读取使能信号 . CPU正在尝试读取该寄存器 .

这是一种有效的做事方式吗?我真的不喜欢自己使用读取启用作为时钟的想法 . 我在Verilog中写了一个使用时钟来检测DATA_READ的上升沿:

always@(posedge CLK, negedge RESETn )
begin
    if(RESETn  == 1'b0) begin        

    end else begin


                last_usr_read_n <= usr_read;
                // Next state logic, only transition on de-assertion of usr_read
                if (last_usr_read_n == 1'd0 && usr_read == 1'd1) begin
                    // check next state logic
                    envm_internal_address <= envm_internal_address + 18'h2; // incrmeent address counter
                    incremented<= incremented^ 1'b1;

                end
        endmodule

我注意到在执行期间VHDL停止改变incremented_tmp,而我的verilog代码继续按预期执行 .

我们遇到的主要问题是设计在寒冷时不起作用 . 我不知道为什么 . 设计中有一堆闩锁,我已尽力去除 . 剩下的就是这样的代码(并且有很多代码) . 我的问题是:这是一个为触发器计时的有效方法吗?它会引起我们所看到的意外问题吗?

谢谢,尼克

2 回答

  • 2

    VHDL代码在DATA_READ信号上创建一个生成的时钟,与Verilog代码的等效代码不同 . 虽然这在某种意义上肯定是“有效的”,因为它是可综合的,如果不能正确约束,这可能会产生时间问题和边缘行为,就像你在寒冷和炎热时所看到的那样 . 首选解决方案是使用同步边沿检测电路替换生成的时钟,就像您在Verilog代码中所做的那样 .

    不幸的是,如果您需要清理大量代码,我不知道自动执行此操作的好方法 . 如果代码遵循这些构造的相同通用结构,则可以尝试搜索和替换 . 我建议开发一个可靠的回归测试套件(如果还没有),以验证您的更改没有任何不受欢迎的副作用 .

    或者,您可以尝试在布局布线工具中识别和约束所有生成的时钟,并注意在时钟域交叉处保持时间 . 特别是如果在同一时钟边沿上启动END_ADDRESS和DATA_READ,则需要通过添加延迟来解决信号之间的竞争条件 . 但是,如果您计划将来重用此代码,那么最好在RTL中修复它 .

  • 0

    代码是一团糟 - 转储它,重新开始 . 关于它的一切都是一面红旗 . 具体问题:

    • 检查CPU数据表 DATA_READ - 它's not usable as a clock if it'不保证单调 . 它可能只是保证了相对于其他信号的设置和保持,所以它可以在其他时间做任何想做的事情,可能为你的代码计时 .

    • 见TJ的回答 . 另请注意,如果原作者使用大量其他信号执行此操作,您的P&R软件可能没有将 DATA_READ 分配给时钟网,并且您的FPGA中的时钟网络已用完

    • incremented_tmp 在时钟分支中分配,但不在异步重置分支中分配 . 这是在寻找麻烦 - 当 N_RESET 为低并且's a clock edge, so you'已经有锁存行为时,它必须保持,并且 N_RESET 的时序相对于 DATA_READ 有问题 .

相关问题