【问题标题】:Index constraint violation in vhdlvhdl 中的索引约束违规
【发布时间】:2016-08-14 13:04:37
【问题描述】:

我的代码模拟有问题。我有一个由双端口内存组成的异步 FIFO。写入与写入时钟同步执行,读取执行提供我要读取的位置的地址。同步由读写指针执行。

基本上我有这样的东西:

architecture rtl of async_memory is 
     type RAM is array (MEM_DEPTH - 1 downto 0) of std_logic_vector(DATAWIDTH - 1 downto 0);
     signal memory : RAM;

begin
     MEM_WRITE:process(clk,rstn)
     begin
     .....
        memory(to_integer(unsigned(addr_wr_i))) <= data_i;
     .....
     end process;

     MEM_READ:data_o <= memory(to_integer(unsigned(addr_rd_i)));

当 MEM_DEPTH 是 2 的幂时,我没有遇到任何问题。当 MEM_DEPTH 不是 2 的幂时,我在为 addr_rd_i 的每条线(读取的地址信号)模拟随机延迟时会遇到一些问题。

需要说明的是,如果我将 MEM_DEPTH 设置为 10,则 addr_rd_i 的宽度为 4 位。 addr_rd_i 的允许值为:

  1. 0000
  2. 0001
  3. 0010
  4. 0011
  5. 0100
  6. 0101
  7. 0110
  8. 0111
  9. 1000
  10. 1001

其他值会导致课程模拟出错(违反索引约束)。问题是由于延迟,我的数字可能大于 1001。例如,如果 addr_rd_i 是 0111 并且我想读取 1000 ,那么我可能在短时间内有 1111 :

  • 0111 -> 1111 -> 1000

现在的问题是:有没有办法避免模拟错误?我想是这样的:

MEM_READ:data_o <= memory(to_integer(unsigned(addr_rd_i)) mod MEM_DEPTH);

我唯一(大)担心的是我可能无法为综合保留相同版本的文件,所以我需要 2 个文件,一个用于综合,一个用于模拟。

【问题讨论】:

    标签: vhdl simulation fifo digital-logic


    【解决方案1】:

    为合成器和 sim 保持相同的文件!!!

    有和没有“mod MEM_DEPTH”的综合。如果它们的大小相同,那么综合优化已经去掉了 MOD 运算符……那么,没问题。

    我的首选方法:编写一个“to_address”函数来执行所有类型转换,返回一个有效地址。在 --pragma translate off--pragma translate on 之间包装一个涉及 MOD 运算符的 return 语句(有关实际接受的语法,请咨询您的合成器工具)。用一个简单的 return 语句跟随它......

    请注意,可能首先应将读取和写入地址声明为无符号。每当您级联类型转换时,设计都可能有问题......

    function to_address(addr : unsigned) return natural is
       temp : natural := to_integer(addr);
    begin
       --pragma translate off
       return temp mod MEM_DEPTH;
       --pragma translate on
       return temp;
    end to_address.
    

    然后模拟将命中第一个return,而综合将下降到第二个。把它注释掉,坚持在代码审查的时候手动检查这个功能......

    【讨论】:

      【解决方案2】:

      抛开为什么有人想要将时间抖动刺激应用于零时间模型的问题,除了使用函数调用来“过滤”地址之外,还有另一种解决方案。

      异步 ​​RAM 使用的经典模型将包括一个读使能,用于通过要求地址在读使能为真期间保持稳定来降低功耗。降低 EMI 也与节能齐头并进。这同样可以应用于真正的异步写入端口,该端口需要使用仅在地址稳定时发生的写入使能来发出非时钟写入信号。时钟读取和写入很容易,假设地址在时钟边缘是稳定的。

      VHDL 中的默认模型是对切换延迟进行建模的惯性延迟 - 与 OP 相关,其中所有地址“位”不会同时传播,导致零时间存储器的索引范围越界内存大小不是 2 的幂时的模型。

      惯性延迟也有剔除时间,用于消除比剔除时间短的脉冲。要求拒绝时间小于相关延迟,并且拒绝时间默认为信号分配的第一个波形元素(可以是唯一元素)中指定的延迟时间

      (参见 IEEE Std 1076-2008 10.5.2 简单信号分配。)

      信号更新在 VHDL 中安排在投影输出波形队列中,其中包含值和值更新发生的时间。

      我们不能简单地安排带有拒绝时间的 data_o 更新,因为排队的值需要读取当前内存内容。

      我们可以使用惯性延迟模型过滤掉 read_addr_i 输入上的开关噪声,该模型依赖于它的拒绝限制。

      因为您需要一个整数(或自然)索引来读取索引内存,您可以添加另一个信号,保持读取地址的整数值并执行脉冲拒绝(以及等于或大于拒绝时间的分配延迟表达式)。

      除此之外,IEEE Std 1076.6-2004(RTL 综合,现已撤销)是生产硬件的受支持综合构造的基础。合成供应商仍会以此为起点。在 8.8.4 信号赋值语句中我们可以看到延迟机制被忽略了。 after 和 after 后面的时间表达式也被忽略 (8.8.4.1)。

      因此我们可以在零时间模型中添加时序以支持仿真中的脉冲抑制:

      architecture fum of async_memory is
          type RAM is array (MEMDEPTH - 1 downto 0) of 
                  std_logic_vector(DATAWIDTH - 1 downto 0);
          signal memory:  RAM;
          signal addr_rd: natural;
      begin
      
      MEM_WRITE:
          process( clk, rstn)
          begin
              if rstn = '0' then
                  memory <= (others => (others => '0'));
              elsif rising_edge(clk) then
                  if wen = '0' then
                      memory(to_integer(unsigned(addr_wr_i))) <= data_i;
                  end if;
              end if;
          end process;
      MEM_READ:
          data_o <= memory(addr_rd);
      PULSE_REJECT:
          addr_rd <= reject 1.8 ns inertial to_integer(unsigned(addr_rd_i)) after 1.9 ns;
      end architecture;
      

      拒绝限制是根据模型时钟周期(此处为 10 ns)选择的,我们看到地址需要 1.9 ns 才能变为有效,表示读取延迟(请记住,分配延迟必须等于或大于拒绝限制)。拒绝限制表示任意两条地址线之间的切换时间差。

      在测试平台中,我们可以对 OP 的示例进行建模:

      STIMULI:
          process
          begin
              wait for 6 ns;
              rstn <= '0';
              wait for 10 ns;
              rstn <= '1';
              wait for 20 ns;
              data_i <= x"ac";
              addr_wr_i <= x"8";
              wen <= '0';
              wait for 10 ns;
              wen <= '1';
              addr_rd_i <= "0111";
              wait for 10 ns;
              addr_rd_i(addr_rd_i'LEFT)  <= '1';
              wait for 1.7 ns;
              addr_rd_i(addr_rd_i'LEFT -1 downto 0) <= (others => '0');
              wait for 8.3 ns;
              wait;
          end process; 
      

      将地址从 0111 翻转到 1000,MSB 比 LSB 快。

      这给了我们:

      地址值 F 持续时间低于拒绝限制。

      注意异步重置用于将内存内容归零。

      【讨论】:

        猜你喜欢
        • 2022-01-23
        • 2015-11-03
        • 2018-01-10
        • 2018-06-28
        • 2013-11-27
        • 2014-11-29
        • 1970-01-01
        • 2020-03-28
        • 1970-01-01
        相关资源
        最近更新 更多