【问题标题】:Generic vhdl design with multiple drivers具有多个驱动程序的通用 vhdl 设计
【发布时间】:2015-06-06 11:17:29
【问题描述】:

我正在尝试编写一些 VHDL 代码,其目的是获取一些外部输入信号并将它们重定向到一些特定的输出。所有信号都由它们自己的外部时钟驱动。我正在设计和测试这个,所以下面的代码可能不完全准确。

此外,我尝试在输入端口和输出端口上锁存或缓冲输入信号,以确保信号在 FPGA 内部和外部 PCB 上具有最长的传播时间,以避免时序违规。这是我知道实现这一目标的唯一方法。

现在,解决问题。这基本上是一个具有多个时钟的通用架构,所以我使用生成语句来生成不同的进程块(主要是因为我的模拟器拒绝编译代码)。但是我遇到了一个问题,即多个进程驱动相同的信号。

如果我查看 input_process_gen,我可以使用 generate 语句,在这种情况下我会得到多个驱动程序。或者我可以使用循环,但是模拟器会抱怨上升沿时钟语句。所以我想知道如何做到这一点。使用已解决的信号是个好主意吗?它会起作用吗?不过,我不完全确定如何为这些复杂的信号编写一个。还是 VHDL 的新手。

也许有更好的解决方案? 可能还有其他可以改进的地方,如果是这样,我愿意听取可能的改进。谢谢。

library ieee;
use ieee.std_logic_1164.all;

package generic_types is
    type signal_array is array (natural range <>, natural range <>) of std_logic;
    type port_array is array (natural range <>, natural range <>) of bit;
    type clk_array is array (natural range <>) of std_logic;
end package;

library ieee;
use work.generic_types.all;
use ieee.std_logic_1164.all;

entity generic_switch_fabric is
    generic (Inputs, Outputs, Bits: Integer);
    port
    (
        clk_in: in clk_array(Inputs - 1 downto 0);
        clk_out: out clk_array(Outputs - 1 downto 0);
        rst_n: in std_logic;
        input: in signal_array(Inputs - 1 downto 0, Bits - 1 downto 0);
        output: out signal_array(Outputs - 1 downto 0, Bits - 1 downto 0);
        port_switcher: in port_array(Inputs - 1 downto 0, Outputs - 1 downto 0)
    );
end entity;

architecture RTL of generic_switch_fabric is
    signal clocked_input: signal_array(Inputs - 1 downto 0, Bits - 1 downto 0);
    signal clocked_output: signal_array(Outputs - 1 downto 0, Bits - 1 downto 0);
    signal clk_out_int: clk_array(Outputs - 1 downto 0);
begin
    clk_process_gen: for input in 0 to Inputs - 1 generate
    clk_process_gen: for output in 0 to Outputs - 1 generate
        clk_process: process(clk_in, port_switcher)
        begin
            -- Propagate input clocks to output clocks
            if (port_switcher(input, output) = '1') then
                clk_out_int(output) <= clk_in(input);
            else
                clk_out_int(output) <= 'Z';
            end if;
        end process;
    end generate;
    end generate;

    clk_process_fwrd: for output in 0 to Outputs - 1 generate
        clk_process: process(clk_out_int)
        begin
            -- Propagate input clocks to output clocks
            clk_out(output) <= clk_out_int(output);
        end process;
    end generate;

    input_process_gen: for input_idx in 0 to Inputs - 1 generate
        input_process: process(clk_in)
        begin
            -- Register on inputs
    --      for input_idx in 0 to Inputs - 1 loop
                if (rising_edge(clk_in(input_idx))) then
                    for output_idx in Bits - 1 downto 0 loop
                        clocked_input(input_idx, output_idx) <= input(input_idx, output_idx);
                    end loop;
                end if;
        --  end loop;
        end process;
    end generate;

    output_process_gen: for output_idx in 0 to Outputs - 1 generate
        output_process: process(clk_out_int)
        begin
            -- Register on outputs
            if (rising_edge(clk_out_int(output_idx))) then
                for input_idx in Bits - 1 downto 0 loop
                    output(output_idx, input_idx) <= clocked_output(output_idx, input_idx);
                end loop;
            end if;
        end process;
    end generate;

    -- rst_process: process(rst_n)
    -- begin
        -- if (rst_n = '0') then
            -- clocked_output <= (others => (others => '0'));
        -- else
            -- clocked_output <= (others => (others => 'Z'));
        -- end if;
    -- end process;

    switcher_generation: for i in 0 to Inputs - 1 generate
        switch_process: process(clocked_input, port_switcher) is
        begin
            clocked_output <= (others => (others => 'Z'));

            -- ...For every output to port to output it to...
            for j in 0 to Outputs - 1 loop

                -- ...If input it supposed to be output to this port...
                if (port_switcher(i, j) = '1') then

                    -- ...Copy all the bits from the input to the output...
                    for k in 0 to Bits - 1 loop
                        clocked_output(j, k) <= clocked_input(i, k);
                    end loop;
                end if;
            end loop;
        end process;
    end generate;
end architecture RTL;

【问题讨论】:

    标签: generics vhdl


    【解决方案1】:
    clk_process_gen: for input in 0 to Inputs - 1 generate
    clk_process_gen: for output in 0 to Outputs - 1 generate
        clk_process: process(clk_in, port_switcher)
        begin
            -- Propagate input clocks to output clocks
            if (port_switcher(input, output) = '1') then
                clk_out_int(output) <= clk_in(input);
            else
                clk_out_int(output) <= 'Z';
            end if;
        end process;
    end generate;
    end generate;
    

    这将生成所有连接到clk_int(output)input 信号。现代 FPGA 不支持 internal 逻辑的三态驱动程序,因此这必然会因“多个驱动程序”错误而失败。

    您需要改用多路复用器方法:

    clk_process_gen: for output in 0 to Outputs - 1 generate
        clk_process: process(clk_in, port_switcher)
        begin
            -- Propagate input clocks to output clocks
            clk_out_int(output) <= clk_in(port_switcher(output));
        end process;
    end generate;
    

    这需要更改port_array 的定义:type port_array is array (natural range &lt;&gt;) of natural;

    请注意,如果没有时钟专用多路复用器,则不建议多路复用时钟,它不支持超过 2 个时钟 AFAIK。因此,您的输出会出现偏差问题,并且在更改配置时可能会出现故障。

    【讨论】:

    • 啊,这很酷。所以我将不得不尝试一种多路复用方法。谢谢。另外,是的,现在不确定时钟。我必须在 FPGA 外部添加一些 PLL 来“修复”时钟,或者只是以某种方式将时钟路由到外部。但这是以后的问题。
    猜你喜欢
    • 1970-01-01
    • 2015-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多