You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

VHDL实现主从D触发器报错:无法写入IN模式接口D的解决方法

解决VHDL主从D触发器的端口赋值错误与Altera D2引脚分配问题

错误原因分析

你遇到的"无法写入IN模式的接口对象'D'"错误,核心问题是VHDL的输入端口(IN模式)不能在模块内部被赋值。你的代码里写了D<=SW(0);,但如果D是被定义为IN类型的端口,模块内部只能读取它的值,不能给它赋值——SW(0)应该作为外部输入连接到D端口,而不是反过来在结构体里给D赋值。

正确的主从D触发器实现步骤

1. 完整的VHDL代码(包含实体与结构体)

首先要明确顶层模块的端口定义,把SW(0)SW(1)作为顶层的输入,LEDR作为输出,然后在结构体里实例化门电路和锁存器:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- 顶层模块实体定义
entity MasterSlaveDFF is
    Port (
        SW : in STD_LOGIC_VECTOR(1 downto 0);  -- SW(0)=D输入, SW(1)=Clk输入
        LEDR : out STD_LOGIC_VECTOR(2 downto 0) -- LEDR(0)=D, LEDR(1)=Clk, LEDR(2)=Q输出
    );
end MasterSlaveDFF;

architecture Structural of MasterSlaveDFF is
    -- 声明子模块:非门
    component notGate
        Port (
            input : in STD_LOGIC;
            output : out STD_LOGIC
        );
    end component;
    
    -- 声明子模块:门控D锁存器
    component gdlatch
        Port (
            En : in STD_LOGIC;
            D : in STD_LOGIC;
            Q : out STD_LOGIC;
            Qn : out STD_LOGIC
        );
    end component;
    
    -- 内部信号声明
    signal invOut1, invOut2 : STD_LOGIC;
    signal Dout : STD_LOGIC;
    signal Q, notQ : STD_LOGIC;
    
begin
    -- 把SW的输入映射到输出显示(读取输入而非赋值给IN端口)
    LEDR(0) <= SW(0);  -- 显示D输入状态
    LEDR(1) <= SW(1);  -- 显示Clk输入状态
    LEDR(2) <= Q;      -- 显示触发器最终输出Q
    
    -- 实例化非门,生成CLK的反相信号
    G1: notGate port map(input => SW(1), output => invOut1);
    G2: notGate port map(input => invOut1, output => invOut2);
    
    -- 实例化主锁存器(由~CLK控制)
    G3: gdlatch port map(En => invOut1, D => SW(0), Q => Dout, Qn => open);
    -- 实例化从锁存器(由CLK控制)
    G4: gdlatch port map(En => invOut2, D => Dout, Q => Q, Qn => notQ);

end Structural;

2. 关键修正点

  • 顶层模块的SW作为输入端口,直接读取SW(0)作为D输入、SW(1)作为Clk输入,彻底避免了给IN端口赋值的错误。
  • 子模块实例化时,直接用SW(0)作为gdlatch的D输入,无需额外定义中间D端口。
  • 移除了错误的D<=SW(0);Clk<=SW(1);赋值语句,改为直接将输入信号映射到显示LED或子模块端口。

Altera D2开发板的引脚分配

要把SW(0)SW(1)LEDR(0-2)绑定到硬件引脚,有两种便捷方式:

方式1:Quartus Prime图形化分配

  1. 打开Quartus Prime,进入Assignment > Assignment Editor
  2. Category栏选择Locations
  3. 左侧To列选择对应信号:SW[0]SW[1]LEDR[0]LEDR[1]LEDR[2]
  4. 右侧Location栏输入D2开发板的实际引脚号(比如SW0对应PIN_AA13,SW1对应PIN_Y13,LEDR0对应PIN_AB12,具体以开发板手册为准)。

方式2:代码内添加引脚约束

直接在实体声明后添加attribute location属性,示例如下:

entity MasterSlaveDFF is
    Port (
        SW : in STD_LOGIC_VECTOR(1 downto 0);
        LEDR : out STD_LOGIC_VECTOR(2 downto 0)
    );
    -- 替换为D2开发板实际引脚号
    attribute location : string;
    attribute location of SW(0) : signal is "AA13";
    attribute location of SW(1) : signal is "Y13";
    attribute location of LEDR(0) : signal is "AB12";
    attribute location of LEDR(1) : signal is "AC12";
    attribute location of LEDR(2) : signal is "AD12";
end MasterSlaveDFF;

额外注意事项

  • 确保notGategdlatch子模块的逻辑正确,比如gdlatch需满足:当En为高时锁存D输入,低电平时保持当前状态。
  • 编译前确认所有子模块都已添加到项目中,避免编译报错。

内容的提问来源于stack exchange,提问作者George Nemoukos

火山引擎 最新活动