如何在不创建新输入信号的情况下编写具有多个输入的多路复用器?

Posted

技术标签:

【中文标题】如何在不创建新输入信号的情况下编写具有多个输入的多路复用器?【英文标题】:How to Write A Mux With Several Inputs Without Creating a New Input Signal? 【发布时间】:2015-03-24 10:50:11 【问题描述】:

如果无法做到这一点,请给我一个简单的“否”,或许还有一个简短的答案,说明原因,但我想仔细检查一下,这无法做到。

我有这个过程:

process(clk_p)
begin
    if rising_edge(clk_p) then
        if rst_i = '1' then
            stored_events <= (others => '0');
        else
            if mode_triggered = '1' and ptr = 0 and read_state = ST_ENABLE then
                stored_events <= stored_events;
            elsif mode_triggered = '1' then
                stored_events <= stored_events + 1;
            elsif ptr = 0 and read_state = ST_ENABLE then
                stored_events <= stored_events - 1;
            end if;
        end if;
    end if;
end process;

是的,这不是很好,为什么我要通过将其转换为适当的 case mux 来帮助合成。

你可以这样做:

sel(0) <= '1' when mode_triggered= = '1' else '0';
sel(1) <= '1' when ptr = 1 else '0'; 
sel(2) <= '1' when read_state = ST_ENABLE else '0';

case sel is 
    when "111" => 
        stored_events <= stored_events; -- and so on...

虽然我要更改几个进程,但我还是要创建更多的信号名称。所以……

我想知道是否有某种我可以喜欢的方式(尽管不完全确定最终的 when others 会如何工作):

case mode_triggered, ptr, read_state is 
    when '1', 0, ST_ENABLE =>
        stored_events <= stored_events;

【问题讨论】:

您的第一个流程示例已经是一个多路复用器。它是一个用于保存、递增和递减的多路复用器,以及一个带同步复位的 D 触发器。该多路复用器通常被吸收到 LUT 中。因此,如果您在 RTL 视图中打开您的设计并查找 LUT 方程,您会在其中找到多路复用器方程。 关于下一个合成,我会研究一下。只是看起来有点凌乱,我通常更喜欢案例陈述的外观。如果没有按照我想要的方式编写多路复用器的新方法,我将使用额外的信号。 以上内容是否也应该以else 结束以捕获所有其他组合? else 情况被隐含地涵盖了,因为它托管在时钟进程中,否则会导致闩锁。 【参考方案1】:

您可能可以使用记录和/或 VHDL-2008 语法来实现您所寻求的,但我不建议这样做。

您不仅会失去可读性,而且我严重怀疑您会获得任何综合收益。

当我查看您的代码时,我没有看到任何多路复用器。相反,我看到一个带有同步复位和时钟启用端口的向上/向下计数器。如果你愿意,你可以这样写:

clk_en <= '0' when mode_triggered = '1' and ptr = 0 and read_state = ST_ENABLE else
          '1' when mode_triggered = '1' or (ptr = 0 and read_state = ST_ENABLE) else
          '0';
up <= '1' when mode_triggered = '1' else '0';

process(clk_p)
begin
    if rising_edge(clk_p) then
        if rst_i = '1' then
            stored_events <= (others => '0');
        elsif clk_en = '1' then
            if up = '1' then
                stored_events <= stored_events + 1;
            else
                stored_events <= stored_events - 1;
            end if;
        end if;
    end if;
end process;

所有三种编写代码的方式都应该导致相同的网表(希望如此),它们只是可读性不同。就个人而言,我更喜欢您的第一次尝试,因为它来自您正在实现的功能,但这一切都是偏好。我也不喜欢 mux 方法(对于这种情况)。

根据经验,不要写信给合成器帮助,除非你也有。查看综合报告和生成的网表,仅在您不喜欢所见内容时进行调整。与我们人类理解充满多路复用器和逻辑门的代码的功能相比,合成器更擅长从代码中提取电路,就像您的第一次尝试一样。

【讨论】:

很有趣,谢谢。我会保持最初的方式。我很好奇这个问题的替代语法,而且确实总是有新的东西要学习=D【参考方案2】:

另一种变体(上下是布尔值)可能有助于提高可读性

down <= ptr = 0 and read_state = ST_ENABLE;
up   <= mode_triggered and not down;

process(clk_p)
begin
    if rising_edge(clk_p) then
        if rst_i = '1' then
            stored_events <= (others => '0');
        else
            if up then
                stored_events <= stored_events + 1;
            elsif down then
                stored_events <= stored_events - 1;
            end if;
        end if;
    end if;
end process;

【讨论】:

以上是关于如何在不创建新输入信号的情况下编写具有多个输入的多路复用器?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不超过最大文档大小的情况下编写聚合?

你好!无论如何要在不使用联合的情况下编写类似的查询吗?

如何在不重复自己的情况下编写三元运算符(又名 if)表达式

我可以在不编写扩展的情况下编写 FlexBuilder 脚本吗?

在不违反 SRP、OCP、DRY 的情况下编写测试

如何在不使用已弃用的类的情况下编写 Hadoop map reduce 作业?