具有多个驱动程序的通用vhdl设计

时间:2015-06-06 11:17:29

标签: generics vhdl

我正在尝试编写一些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;

1 个答案:

答案 0 :(得分:0)

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;

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

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

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_arraytype port_array is array (natural range <>) of natural;

的定义

请注意,如果没有时钟专用多路复用器,则不建议使用多路复用时钟,因为它不支持超过2个时钟AFAIK。因此,当您更改配置时,输出会出现偏斜问题,以及潜在的故障。