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

时间:2016-07-18 18:01:20

标签: vhdl verilog fpga

我在工作中继承了一些传统的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正在尝试读取该寄存器。

这是一种有效的做事方式吗?我真的不喜欢自己使用read enable作为时钟的想法。我在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 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:0)

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

  1. 检查DATA_READ的CPU数据表 - 如果它不能保证单调,则它不能用作时钟。它可能只是保证了相对于其他信号的设置和保持,因此它可以在其他时间执行任何操作,可能为您的代码提供时钟。
  2. 见TJ的回答。另请注意,如果原作者使用大量其他信号执行此操作,并且您的FPGA中已经没有时钟网,那么您的P&amp; R软件可能没有将DATA_READ分配给时钟网
  3. incremented_tmp在时钟分支中分配,但不在异步重置分支中分配。这是一个问题 - 它必须在N_RESET为低并且有时钟优势时保持,因此您已经获得了锁存行为,并且问题与N_RESET相关的时间有关。 DATA_READ