Mux для портов INOUT

Эй, ребята, я пытаюсь обменять 2 пары сигналов INOUT, но пока без особого успеха.

У меня есть два контроллера PS/2, и я хотел бы обменять сигналы PS2(1) на PS2(2) и одновременно сигналы PS2(2) на PS2(1).

Возможно, это проще объяснить с помощью действующего (снятого) кода.

-- external ports 
ps2_clk_io        : inout std_logic     := 'Z';
ps2_data_io       : inout std_logic     := 'Z';
ps2_mouse_clk_io  : inout std_logic     := 'Z';
ps2_mouse_data_io : inout std_logic     := 'Z';


-- signals
signal ps2_mode_s   : std_logic := '0';
signal PS2K_DAT_IN  : std_logic;
signal PS2K_DAT_OUT : std_logic;
signal PS2K_CLK_IN  : std_logic;
signal PS2K_CLK_OUT : std_logic;
signal PS2M_DAT_IN  : std_logic;
signal PS2M_DAT_OUT : std_logic;
signal PS2M_CLK_IN  : std_logic;
signal PS2M_CLK_OUT : std_logic;

signal ps2_data_out : std_logic;
signal ps2_clk_out      : std_logic;
signal ps2_mouse_data_out   : std_logic;
signal ps2_mouse_clk_out    : std_logic;

 -- LOGIC BLOCK
 -- PS/2 keyboard
 PS2K_DAT_IN <= ps2_data_io when ps2_mode_s = '0' else ps2_mouse_data_io;
 PS2K_CLK_IN <= ps2_clk_io  when ps2_mode_s = '0' else ps2_mouse_clk_io;

 ps2_data_out <= PS2K_DAT_OUT when ps2_mode_s = '0' else PS2M_DAT_OUT;
 ps2_clk_out  <= PS2K_CLK_OUT when ps2_mode_s = '0' else PS2M_CLK_OUT;

 ps2_data_io <= '0' when ps2_data_out = '0' else 'Z';
 ps2_clk_io  <= '0' when ps2_clk_out  = '0' else 'Z';

 -- PS/2 Mouse
 PS2M_DAT_IN <= ps2_mouse_data_io when ps2_mode_s = '0' else ps2_data_io;
 PS2M_CLK_IN <= ps2_mouse_clk_io  when ps2_mode_s = '0' else ps2_clk_io;

 ps2_mouse_data_out <= PS2M_DAT_OUT when ps2_mode_s = '0' else PS2K_DAT_OUT;
 ps2_mouse_clk_out  <= PS2M_CLK_OUT when ps2_mode_s = '0' else PS2K_CLK_OUT;

 ps2_mouse_data_io <= '0' when ps2_mouse_data_out = '0' else 'Z';
 ps2_mouse_clk_io  <= '0' when ps2_mouse_clk_out  = '0' else 'Z';

Как видите, я бы хотел обмениваться сигналами между мышью и клавиатурой, используя управляющий сигнал "ps2_mode_s". Если этот сигнал равен "0", мне нужна клавиатура на первом порту и мышь на втором. Если это "1", опозит, мышь на первом порту и клавиатура на втором.

Я уже попробовал некоторые варианты, но я не нашел правильного решения.

(РЕДАКТИРОВАТЬ) Оба порта, кажется, не отправлять или получать какие-либо данные, если я использую мультиплексор.

(РЕДАКТИРОВАТЬ) Все четыре сигнала подключены к соответствующим модулям. PS2K_DAT_IN, PS2K_CLK_IN, PS2K_DAT_OUT, PS2K_CLK_OUT отправляется на контроллер клавиатуры PS2, а остальные четыре PS2M_DAT_IN, PS2M_CLK_IN, PS2M_DAT_OUT, PS2M_CLK_OUT отправляются на модуль контроллера мыши PS2. Оба модуля работают, если я не использую мультиплексор, подключая сигналы непосредственно к портам INOUT.

PS2K_DAT_IN <= ps2_data_io;
ps2_data_io <= '0' when (PS2K_DAT_OUT = '0') else 'Z';
PS2K_CLK_IN <= ps2_clk_io;
ps2_clk_io  <= '0' when (PS2K_CLK_OUT = '0') else 'Z';

PS2M_DAT_IN <= ps2_mouse_data_io;
ps2_mouse_data_io <= '0' when (PS2M_DAT_OUT = '0') else 'Z';
PS2M_CLK_IN <= ps2_mouse_clk_io;
ps2_mouse_clk_io <= '0' when (PS2M_CLK_OUT = '0') else 'Z';

Может кто-нибудь помочь, пожалуйста?

2 ответа

Решение

Хитрость заключается в том, чтобы поместить два мультиплексора (один для ввода, один для вывода) перед каждым двунаправленным буфером вывода.

library ieee;
use ieee.std_logic_1154.all;

entity PS2Switch is
    port(
        -- control
        mode_s : in std_logic;
        -- keyboard ps/2 block
        kbd_clk_in   : in  std_logic;
        kbd_clk_out  : out std_logic;
        kbd_data_in  : in  std_logic;
        kbd_data_out : out std_logic;
        -- mouse ps/2 block
        mouse_clk_in   : in  std_logic;
        mouse_clk_out  : out std_logic;
        mouse_data_in  : in  std_logic;
        mouse_data_out : out std_logic;
        --port A
        prtA_clk  : inout std_logic;
        prtA_data : inout std_logic;
        --port B
        prtB_clk  : inout std_logic;
        prtB_data : inout std_logic
        );
end entity;

architecture rtl of PS2Switch is
    signal prtA_clk_out  : std_logic;
    signal prtA_data_out : std_logic;
    signal prtB_clk_out  : std_logic;
    signal prtB_data_out : std_logic;
begin
    -- output muxes
    kbd_clk_out    <= prtA_clk  when mode_s = '0' else prtB_clk;
    kbd_data_out   <= prtA_data when mode_s = '0' else prtB_data;
    mouse_clk_out  <= prtA_clk  when mode_s = '1' else prtB_clk;
    mouse_data_out <= prtA_data when mode_s = '1' else prtB_data;

    -- input muxes
    prtA_clk_out  <= kbd_clk_in  when mode_s = '0' else mouse_clk_in;
    prtA_data_out <= kbd_data_in when mode_s = '0' else mouse_data_in;
    prtB_clk_out  <= kbd_clk_in  when mode_s = '1' else mouse_clk_in;
    prtB_data_out <= kbd_data_in when mode_s = '1' else mouse_data_in;

    -- tristate buffers (output pins)
    prtA_clk  <= '0' when prtA_clk_out  = '0' else 'Z';
    prtA_data <= '0' when prtA_data_out = '0' else 'Z';
    prtB_clk  <= '0' when prtB_clk_out  = '0' else 'Z';
    prtB_data <= '0' when prtB_data_out = '0' else 'Z';
end architecture;

Это скорее смесь сигналов у вас там. Я думаю, что в этом случае я бы предпочел схему. К сожалению, эта опция недоступна на сайте SE (как на сайте EE).

С первого взгляда у меня сложилось впечатление, что вы пытаетесь построить двунаправленный путь через ПЛИС. Я пытался понять, что происходит, но безуспешно.

Я застрял, потому что вы никогда не назначаете значение PS2K_CLK_OUT, но вы используете сигнал. То же самое для PS2K_DAT_OUT, Как таковой код определенно ошибочен. Я предлагаю вам исправить эту часть и упростить отслеживание происходящего, добавив больше комментариев типа:

-- Mode A: Data comes from X and goes to Y

В общем:
Насколько я знаю, невозможно построить действительно двунаправленный путь через FPGA. (С истинно, я имею в виду, что он самостоятельно определяет направление сигнала). Вам нужен сигнал, который переключает порты между режимами ввода и вывода. Если это то, что вам нужно, единственным вариантом является использование внешнего аналогового переключателя или реле.

Другие вопросы по тегам