9

我正在研究 FIR 滤波器,特别是延迟线。x_delayed被初始化为全零。

type slv32_array is array(natural range <>) of std_logic_vector(31 downto 0);
...
signal x_delayed : slv32_array(0 to NTAPS-1) := (others => (others => '0'));

这不起作用:

x_delayed(0) <= x;             -- Continuous assignment

DELAYS : process(samp_clk)
begin
    if rising_edge(samp_clk) then
        for i in 1 to NTAPS-1 loop
            x_delayed(i) <= x_delayed(i-1);
        end loop;
    end if; -- rising_edge(samp_clk)
end process;

模拟


但这确实:

DELAYS : process(samp_clk)
begin
    if rising_edge(samp_clk) then
        x_delayed(0) <= x;           -- Registering input
        for i in 1 to NTAPS-1 loop
            x_delayed(i) <= x_delayed(i-1);
        end loop;
    end if; -- rising_edge(samp_clk)
end process;

模拟

这个“解决方案”的问题是第一个元素x_delayed被一个样本延迟了,这是应该的。(其余代码预计x_delayed(0)当前示例)。

我正在使用 Xilinx ISE 13.2,使用 ISim 进行仿真,但这也被证实使用 ModelSim 进行仿真。

是什么赋予了?


编辑:

问题本质上是,即使似乎x_delayed(0)没有被驱动在里面process它是

在实施了Brian Drummond 的想法后,它完美运行:

x_delayed(0) <= x;

-- Synchronous delay cycles.
DELAYS : process(samp_clk)
begin
    -- Disable the clocked driver, allowing the continuous driver above to function correctly.
    -- https://stackoverflow.com/questions/18247955/#comment26779546_18248941
    x_delayed(0) <= (others => 'Z');        

    if rising_edge(samp_clk) then
        for i in 1 to NTAPS-1 loop
            x_delayed(i) <= x_delayed(i-1);
        end loop;
    end if; -- rising_edge(samp_clk)
end process;

模拟


编辑2:

我接受了OllieB 的建议来摆脱for循环。我不得不改变它,因为我x_delayed的索引来自(0 to NTAPS-1),但我们最终得到了这个漂亮的小过程:

x_delayed(0) <= x;

DELAYS : process(samp_clk)
begin
    x_delayed(0) <= (others => 'Z');
    if rising_edge(samp_clk) then
        x_delayed(1 to x_delayed'high) <= x_delayed(0 to x_delayed'high-1);
    end if; -- rising_edge(samp_clk)
end process;

编辑3:

OllieB 的下一个建议之后,事实证明这x_delayed(0) <= (others => 'Z')是不必要的,因为他之前的更改。以下工作正常:

x_delayed(0) <= x;

DELAYS : process(samp_clk)
begin    
    if rising_edge(samp_clk) then
        x_delayed(1 to x_delayed'high) <= x_delayed(0 to x_delayed'high-1);
    end if;
end process;
4

4 回答 4

13

在第一种情况下,x_delayed(0)实际上有两个驱动程序,在进程之外,beingx_delayed(0) <= x和一个在 DELAY 进程内的隐式驱动程序。

进程内部的驱动程序是 VHDL-2002 标准 (IEEE Std 1076-2002) 部分“6.1 名称”中描述的称为“最长静态前缀”的 VHDL 标准概念的结果,以及带有循环变量的循环构造 i,由此x_delayed(i)is 的最长静态前缀x_delayed

VHDL 标准随后在“12.6.1 驱动程序”一节中进一步描述了进程的驱动程序,其中说“......在进程语句中存在一个给定标量信号 S 的驱动程序,前提是至少有一个信号分配语句在该过程语句中,并且该信号分配语句的目标信号的最长静态前缀表示 S ...”。

因此,作为一个(可能令人惊讶的)结果,x_delayed(0)在 DELAY 过程中有一个驱动程序,它将所有 std_logic 元素自未分配以来驱动为“U”,从而无论驱动什么值,std_logic 解析函数都会导致结果值为“U”由外部x_delayed(0) <= x

但就您的代码而言,似乎还有更多内容,因为x_delayed(0)从图中可以看出,在模拟输出中实际上有一些“0”值。但是,当我没有完整的代码时,很难进一步深入研究。

查看循环是原因的一种方法是通过替换为手动推出循环for ... loop

x_delayed(1) <= x_delayed(1-1);
x_delayed(2) <= x_delayed(2-1);
...
x_delayed(NTAPS) <= x_delayed(NTAPS-1);

对于将 NTAPS 作为通用的可配置模块,这当然不是一个可用的解决方案,但看到操作与直观预期的一样可能会很有趣。

编辑:根据评论,在上述问题之后的“编辑”部分中列出了多种解决方案。下面显示了一个带有变量的解决方案,如果需要,它允许复杂的表达式。如果不需要复杂的表达式,那么根据OllieB 的建议,可以将分配减少到x_delayed(1 to x_delayed_dir'high) <= x_delayed(0 to x_delayed_dir'high-1)

x_delayed(0) <= x;
DELAYS : process(samp_clk)
  variable x_delayed_v : slv32_array(1 to NTAPS-1);
begin
  if rising_edge(samp_clk) then
    for i in 1 to NTAPS-1 loop
      x_delayed_v(i) := x_delayed(i-1);  -- More complex operations are also possible
    end loop;
    x_delayed(1 to x_delayed_dir'high) <= x_delayed_v;
  end if;  -- rising_edge(samp_clk)
end process;
于 2013-08-15T08:31:36.543 回答
1

在细化过程中,无论循环迭代器的范围如何,都会为 x_delayed 中的所有元素创建驱动程序。因此,x_delayed(0) 有两个与之关联的驱动程序。Std_Logic 和 Std_Logic_Vector 是解析类型(即,当多个驱动程序与这些类型的信号相关联时,解析函数将通过在 std 包中查找表来确定信号的值。有关更多信息,请参阅VHDL 编码样式和方法细节。

于 2013-08-16T01:17:05.930 回答
0

你有问题的原因是逻辑认为你有两件事同时分配给同一个信号——继续分配和寄存器分配循环。与注册实现保持一致。

编辑
如果你有modelsim,你可以使用'trace x'选项,看看它来自哪里。
可能是另一个模拟器也有这个功能,但是对于modelsim我确定它可以工作

于 2013-08-15T07:52:11.407 回答
-1

在你不工作的例子中 x_delayed(0) <= x;

相当于

process(x)
begin
   x_delayed(0) <= x;
end process;

因此,只有当 x 发生变化时,该过程才会分配 x_delayed(0)。因为这是一个信号分配,所以 x_delayed(0) 不会立即改变,它会在一个增量周期后改变。因此,当进程 DELAYS 被调用时,x_delayed(0) 的赋值还没有发生!

如果可以,请在您的流程中为 x_delayed 使用变量。

x_delayed(0) := x;
于 2013-08-15T07:53:58.103 回答