如何使用多路复用逻辑建模两个D触发器

时间:2014-02-20 17:53:19

标签: vhdl

我想使用多路复用器为某些逻辑建模两个D触发器。当多路复用器选择DFF D1(B = 0)时,我希望三个MSB的静态输出为“000”,当多路复用器选择DFF D2(B = 1)时,三个LSB应固定为“111”。

这是我的代码 - 我最初在不检查明显语法错误的情况下盲目输入 - 下面。我不知道如何解决我的问题:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity dff_mux is
Port ( D1, D2 : in  STD_LOGIC_VECTOR(11 DOWNTO 0);
      clk : in  STD_LOGIC;
      rst : IN STD_LOGIC;
      B : in  STD_LOGIC;
  data  : out  STD_LOGIC_VECTOR(11 DOWNTO 0));
end dff_mux;

architecture Behavioral of dff_mux is

signal Q1, Q2 : std_logic_vector(11 downto 0);

begin

process(clk,rst)
begin
    if (rst = '1') then

        Q1<="000000000000";

    elsif (clk'event and clk='1') then

        if (B = '0') then

            -- I want to fix thee MSB to "000"
            -- other bits shall retain their input value
            D1(11) <= '0';
            D1(10) <= '0';
            D1(9) <= '0';
            Q1 <= D1;

        elsif (B = '1') then

            -- fix three LSB to "111"
            -- other bits retain their input value
            D2(2) <= '1';
            D2(1) <= '1';
            D2(0) <= '1';
            Q2 <= D2;

        end if;

    end if;

end process;

-- MUX description: select D1 when B = 0, else select D2 when B = 1

MUX : process(B)
begin

    data <= Q1 when (B = '0') else
            Q2;

end process MUX;

end Behavioral;

提前感谢任何可以帮助我的人。

2 个答案:

答案 0 :(得分:1)

您的VHDL设计说明中存在许多错误。两个流程语句驱动相同的信号(Q1Q2)。第二个进程有三个错误(没有进程语句标签,而标签是在关闭的并发信号赋值语句中指定的,其中顺序信号赋值语句是合适的)。看来第二个流程陈述应该全部消除。

如果要在Q1Q2寄存器的输入上设置多路复用器,则第一个进程无法正常工作。您不能将值分配给块内的正式输入。

您应该直接在流程声明(B Q1内)将Q2个选定值分配给clkelsif

您对D(11)的分配有缺陷(使用==代替<=)。

如果您只为特定信号分配一个值(例如,最长静态前缀D1D2),则它不是多路复用器。请注意,提供的Q2没有重置值。

没有分配地点数据。

如果你正在为课堂作业做这件事,那么在没有学习VHDL的情况下提供答案的人几乎没有什么好处。如果你正在努力学习VHDL,你需要更多并逐步建立练习。

如果我理解你正在尝试做什么,它会看起来像这样:

architecture Behavioral of basculeD is
-- signal Q1, Q2 : std_logic_vector(11 downto 0);
begin

-- process(clk,rst)
-- begin
-- if (rst='1') then Q1<="000000000000";
-- elsif ( clk'event and clk='1') then
-- if (B='0') then 
-- D1(11) =='0'; -- i want to fix the 3MSB of D1 in the "000" ... 
-- D1(10) <='0';
-- D1(9) <='0';
-- Q1<= D1;
-- elsif  (B='1') then 
-- D2(2)<= '1'; -- the 3LSB are fixed to 111 , and defaut value ... 
-- D2(1)<='1';
-- D2(0)<='1';
-- Q2<=D2;
-- end if; 
-- end if;
-- end process;

-- description MUX : select D1 when B=0, else select D2 when B= 1  
-- process( B)
-- begin
-- Q1 <= D1 when B='0' else 
-- Q2<=D2 when B='1'  ;
-- end process MUX;

MUXED_REG:
    process (clk,rst)
    begin
        if rst = '1' then 
            data <= (others => '0'); -- equivalent to "000000000000"
        elsif clk'event and clk = '1' then
        -- the actual multiplexer:
            if B = '0' then
                data <= ("000" & D1(8 downto 0));
            else  -- B = '1', or other values
                data <= (D2(11 downto 3) & "111");
            end if;
        end if;
    end process;
end Behavioral;

您当然可以保留一个中间信号,比如说Q,并用它来代替上面的数据,同时将信号从Q分配到data(输出)。 / p>

使用上述架构代替您的分析。

使用测试台:

library ieee; 
use ieee.std_logic_1164.all;

entity basculeD_test is
end entity;

architecture test of basculeD_test is
    component basculeD is
        port ( 
            d1, d2:  in   std_logic_vector(11 downto 0);
            clk:     in   std_logic;
            rst:     in   std_logic;
            b:       in   std_logic;
            data:    out  std_logic_vector(11 downto 0)
        );
    end component;

    signal d1:      std_logic_vector(11 downto 0) := (others => '1');
    signal d2:      std_logic_vector(11 downto 0) := (others => '0');
    signal clk:     std_logic := '0';
    signal rst:     std_logic := '1';
    signal b:       std_logic := '0';
    signal data:    std_logic_vector(11 downto 0);

begin

CLOCK: 
    process
    begin
        wait for 10 ns;
        clk <= not clk;
        if Now > 100 ns then
            wait;
        end if;
    end process;

RESET:
    process
    begin
        wait for 31 ns;
        rst <= '0';
        wait;
    end process;

DUT:
    basculeD 
        port map (
            d1   => d1,
            d2   => d2,
            clk  => clk,
            rst  => rst,
            b    => b,
            data => data
        );

STIMULUS:
    process
    begin
        wait for 65 ns;
        b <= '1';
        wait;
    end process;

end architecture;

使用MUXED_REG进程的basculeD替换架构:

  

david_koontz @ Macbook:ghdl -a basculeD.vhdl
  david_koontz @ Macbook:ghdl -e basculeD_test
  david_koontz @ Macbook:ghdl -r basculeD_test --wave = basculeD_test.ghw
  david_koontz @ Macbook:open basculeD_test.gtkw(以前保存的保存文件)

给出:

Test bench execution of basculeD_test

当然有可能你试图将存储与多路复用完全分开,这表示你可以使用Q1Q2作为寄存器(并且只需要9位),一个单独的多路复用器(如隐含在原始basculeD architecture)中,允许B在输出Q1上修改后的Q2data寄存器值之间进行操控。

这看起来像这样:

architecture Behavioral of basculeD is
    signal Q1:  std_logic_vector(8 downto 0);
    signal Q2:  std_logic_vector(11 downto 3);
begin
REGS:
process (clk, rst)
begin
    if rst = '1' then
        Q1 <= (others => '0');
        Q2 <= (others => '0');    
    elsif clk'event and clk = '1' then
        Q1 <= D1 (8 downto 0); 
        Q2 <= D2(11 downto 3);
    end if;
end process;

MUX:
process (B,Q1,Q2)
begin
    if B = '0' then
        data <= ("000" & Q1);
    else
        data <= (Q2 & "111");
    end if;
end process;

并给你这样的东西:

basculeD_test with separate MUX

VHDL旨在向读者传达设计规范,当使用某些约定来进行大写时(VHDL在扩展标识符中不区分大小写)和缩进时,它变得更容易。

答案 1 :(得分:0)

欢迎使用StackOverflow!首先,这是一个英文问题&amp;回答网站。请将所有相关术语翻译成英文,即basculeD =&gt; D触发器等。另外,尝试尽可能地描述您的问题,而不会有太多的拼写错误(拼写检查!)或语法错误。这将有助于其他人了解您并有效地帮助您。

无论如何,您的主要问题是,您有输入端口D1和D2,并尝试写入它们。相反,你应该只需要任何你需要的位,而忽略其他位。

不应该尝试写入输入,这是不可能的,你应该试试这个:

Q2 <= D2(11 downto 3) & "111";

该语句从D2获取位11到3,并将它们分配给Q2的第11位到第3位。 Q2的第2位到第0位被赋予常数值“1​​11”。

您应该记住,您无法“重写”输入端口值。您的上一个流程也可以重写为并行语句。

此外,您的设计在某种意义上是独特的,您希望单独存储修改后的值。

考虑一下:

D1 = x“00A”; D2 = x“00B”,B ='0',clk - >上升趋势

现在,Q1 = x“00A”,Q2 = x“???”,数据= Q1 = x“00A”,B ='0',clk ='1'

现在,Q1 = x“00A”,Q2 = x“???”,数据= Q2 = x“???”,B ='1',clk ='1'

当你想在B ='1'和B ='0'之间切换时,你需要至少两个时钟周期来切换你的输出,因为Q1 resp Q2将保持旧的(可能是未初始化的)值。

您的设计可能无法完成您想要的操作。如果您需要多路复用器,请选择多路复用器。如果你想要一个触发器,建立一个触发器。

process(clk,rst)
begin

    if (rst = '1') then

        data <= (others => '0');

    elsif (clk'event and clk='1') then

        if (B = '1') then

            -- Select D2
            data <= D2(11 downto 3) & "111";

        else

            -- Select D1
            data <= "000" & D1(8 downto 0);

        end if;

    end if;

end process;

您可能还想考虑重置是否真的合适以及同步重置是否更有益。