【问题标题】:Mux for INOUT portsINOUT 端口的多路复用器
【发布时间】:2018-07-25 22:05:24
【问题描述】:

大家好,我正在尝试交换 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';

有人可以帮忙吗?

【问题讨论】:

  • 欢迎使用 StackOverflow。也许您可以访问Asking section 以更好地了解如何提出好的问题,尤其是Minimal, Complete, and Verifiable example (MCVE) 是什么。例如,您的问题甚至没有包含对您遇到的问题的清晰描述(错误消息、不需要的行为......),而这绝对是必需的。
  • 对不起,我完全忘记写这个问题了。如果我使用多路复用器,两个端口似乎都不会发送或接收任何数据。
  • 也许您可以提供minimal reproducible example 以及您在实现或模拟方面是否有问题。如果实施,供应商的特定工具链和修订。综合的支持语言是 IEEE Std 1076-2008, 16.8.2.4.10 高阻抗值的解释 ('Z'), IEEE Std 1076.6-2004 (撤回) 6.3.1 三态逻辑来自'Z' assignment . FPGA 综合可能取决于作为器件引脚的分配目标(例如,Vivado 会将内部信号“Z”分配转换为等效逻辑)。如果是模拟,MCVe 将允许检查特定问题。

标签: vhdl fpga inout


【解决方案1】:

诀窍是在每个双向引脚缓冲区之前放置两个多路复用器(一个用于输入,一个用于输出)。

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;

【讨论】:

    【解决方案2】:

    它是你那里的信号的混搭。我认为出于这个原因,我更喜欢示意图。不幸的是,该选项在 SE 站点上不可用(就像在 EE 站点上一样)。

    第一眼我就觉得你在哪里 试图通过 FPGA 构建双向路径。我试图跟踪正在发生的事情,但失败了。

    我被卡住了,因为您从未为 PS2K_CLK_OUT 赋值,但您确实使用了信号。 PS2K_DAT_OUT 也是如此。因此,代码肯定是有缺陷的。 我建议您修复该部分,并通过添加更多类型的 cmets 来更轻松地了解正在发生的事情:

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

    一般来说:
    据我所知,不可能通过 FPGA 构建真正的双向路径。 (真的,我的意思是它自行确定信号方向)。您需要一个在输入和输出模式之间切换端口的信号。如果这是您需要的,您唯一的选择是使用外部模拟开关或继电器。

    【讨论】:

    • 感谢您的回答。所有四个信号都连接到各自的模块。 PS2K_DAT_IN、PS2K_CLK_IN、PS2K_DAT_OUT、PS2K_CLK_OUT 进入 ps2 键盘控制器,其他四个信号进入 ps2 鼠标模块。在这两种情况下,如果我不使用多路复用器,它将模块直接连接到 INOUT 端口。
    猜你喜欢
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多